通过互操作将字符串数组从c#传递到c++
本文关键字:c++ 数组 互操作 字符串 | 更新日期: 2023-09-27 18:05:23
我有一个用c++编写的COM组件,我想通过互操作在我的c#应用程序中调用它的接口。
我要调用的接口定义如下:
c#互操作接口定义:void ICertainInterface.Func(int cnt, ref string colors)
c++定义:
ICertainInterface : IUnknown
{
virtual HRESULT Func(long cnt, BSTR * colors) = 0;
}
这对我来说很清楚,接口是我的应用程序期望的具有特定长度的BSTR数组。第二个参数BSTR * colors应该代表字符串数组中的第一个字符串地址。
下面是我用来从c#应用程序中调用接口的代码:ICertainInterface obj = GetInterface();
string[] strArray = new string[4];
strArray[0] = "aaa";
strArray[1] = "bbb";
strArray[2] = "ccc";
strArray[3] = "ddd";
obj.Func(4, ref strArray[0]);
一旦我运行应用程序,错误给出"试图读写受保护的内存"。如果数组大小仅为1,则不会发生这种情况。在我看来,因为字符串数组是c#中的托管数据。所以内存分配是不可预测的,一旦我传递strArray[0]作为对c++接口的引用,接口将把它作为数组的起始地址,并假设add by 4将获得下一个元素的地址,但这在c#内存分配中不能以相同的方式进行。
我从网上搜索了一些帖子,似乎大多数接口用户"ref string[]"作为指向c#数组的指针,但不像这个"ref string",我只能引用数组中的第一个元素(我甚至不知道它是否是正确的方法,因为在c++中,第一个元素地址相当于数组地址。
进一步,我在excel VBA代码中做了相同的测试,调用相同的接口:
Dim msColor(4) As String
msColor(0) = "aaa"
msColor(1) = "bbb"
msColor(2) = "ccc"
msColor(3) = "ddd"
Dim obj as ICertainInterface
Set obj = GetInterface();
Call obj.Func(4, msColor(0))
这个VBA代码工作完美,没有任何错误。
现在我完全不知道如何在我的c#应用程序中修复这个问题。谁能给我指条路吗?非常感谢。
方法签名不应该是
void ICertainInterface.Func(int cnt, ref string[] colors)
…不是传递数组中的第一个元素,而是传递整个数组?
c#中的数组不像C/c++中的数组;不能只传递对第一个元素的引用,就期望能够使用指针算术方法访问其余元素。
编辑:你可能也不需要ref
关键字在那里。
为了在CLR和非CLR进程之间传递,您可能需要封送为适当的类型这是正确的签名
所以如果你想传递一个字符串,那么
void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.BStr)] ref string colors)
或者如果是数组,那么
void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)] ref string[] colors)
我根据你的代码做了这个解决方案。如果上面的解决方案不适合你,那么你可以尝试找到适合你的应用程序的合适的数组类型/子类型http://msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.110).aspx和字符串类型http://msdn.microsoft.com/en-us/library/s9ts558h(v=vs.110).aspx
使用DllImport属性的例子
如果你想传递一个字符串,那么
[DllImport("yourLib.dll", EntryPoint = "Func")]
public static extern void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.BStr)] ref string colors)
如果是数组,则
[DllImport("yourLib.dll", EntryPoint = "Func")]
public static extern void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)] ref string[] colors)
这可能会帮助你实现相同的,Dll导入通常用于调用winapi