简体   繁体   English

通过互操作将字符串数组从C#传递到C ++

[英]Passing string array from C# to C++ through interop

I have a COM component which is written in C++ which I want to call its interface in my C# application through interop. 我有一个用C ++编写的COM组件,我想通过互操作在我的C#应用​​程序中调用其接口。

The interface which I want to call is defined like this: 我要调用的接口定义如下:

C# interop interface definition: C#互操作接口定义:

void ICertainInterface.Func(int cnt, ref string colors)

C++ definition: C ++定义:

ICertainInterface : IUnknown
{
    virtual HRESULT Func(long cnt, BSTR * colors) = 0;
}

This is clear to me that, the interface is expected a BSTR array with specific lenth from my application. 我很清楚,该接口应该是我应用程序中指定长度的BSTR数组。 The 2nd parameter BSTR * colors suppose to stand for the 1st string address in my string array. 第二个参数BSTR *颜色假设代表我的字符串数组中的第一个字符串地址。

Now this is the code I used to call up the interface from my C# application: 现在,这是我用来从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]);

Once I run the application, error given "Attempted to read or write protected memory". 运行该应用程序后,出现错误“尝试读取或写入受保护的内存”。 This won't happen if the array size is only 1. It seems to me that, because the string array is managed data in C#. 如果数组大小仅为1,则不会发生这种情况。在我看来,因为字符串数组是C#中的托管数据。 So the memory allocation is not predictable, Once I pass strArray[0] as a reference to C++ interface, the interface will take it as the starting address of an array and assume add by 4 will get the address for next element but which could not be go in the same way in C# memory allocation. 因此内存分配是不可预测的,一旦我将strArray [0]作为对C ++接口的引用,该接口将把它作为数组的起始地址,并假定加4将获得下一个元素的地址,但不能在C#内存分配中以相同的方式进行。

I searched some post from online, seems most interfaces user "ref string[]" as the pointer to an C# array but not like this "ref string" which I can only refer to the 1st element in the array (I even don't know if it is the right approach, because in C++ the 1st element address is equivalent to the array address.) 我从网上搜索了一些帖子,似乎大多数接口用户“ ref string []”是指向C#数组的指针,但不喜欢这个“ ref string”,我只能引用数组中的第一个元素(我什至没有知道这是否是正确的方法,因为在C ++中,第一个元素地址等于数组地址。)

Further more, I did a same test in excel VBA code which called the same interface: 此外,我在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))

This VBA code works perfect without any error. 此VBA代码完美无误。

Now I totally have no idea how to fix this in my C# application. 现在我完全不知道如何在我的C#应用​​程序中解决此问题。 Can someone point me a way? 有人可以指点我吗? I would very much appreciate. 我将不胜感激。

Shouldn't the method signature be 方法签名不应该是

void ICertainInterface.Func(int cnt, ref string[] colors)

...and instead of passing the first element in the array, pass the entire array? ...而不是传递数组中的第一个元素,而是传递整个数组?

Arrays in C# don't behave like arrays in C/C++; C#中的数组的行为不像C / C ++中的数组。 you can't just pass a reference to the first element and expect to be able to access the rest of the elements using pointer arithmetic. 您不能只传递对第一个元素的引用,并期望能够使用指针算法访问其余元素。

Edit: You probably don't need the ref keyword in there, either. 编辑:您可能也不需要ref关键字。

You may need to marshal to appropriate type in order to pass between CLR and non CLR processes Here you go with the correct signature 您可能需要封送适当的类型,以便在CLR和非CLR进程之间传递。

so if you are trying to pass a single string then 因此,如果您尝试传递单个字符串,则

void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.BStr)] ref string colors)

or if it is kind of array then 或者如果是数组

void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)] ref string[] colors)

I made this solution based on your code. 我根据您的代码制定了此解决方案。 If above solution does not work for you then you may try finding the appropriate array type/subtype suitable for your application here http://msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.110).aspx and for string types here http://msdn.microsoft.com/en-us/library/s9ts558h(v=vs.110).aspx 如果上述解决方案对您不起作用,则可以尝试在此处找到适合您的应用程序的适当数组类型/子类型http://msdn.microsoft.com/zh-cn/library/z6cfh6e6(v=vs.110).aspx以及有关字符串类型的信息,请参见http://msdn.microsoft.com/zh-cn/library/s9ts558h(v=vs.110).aspx

using DllImport attribute example 使用DllImport属性示例

if you are trying to pass a single string then 如果您尝试传递单个字符串,则

[DllImport("yourLib.dll", EntryPoint = "Func")]
public static extern void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.BStr)] ref string colors)

if it is kind of array then 如果是数组

[DllImport("yourLib.dll", EntryPoint = "Func")]
public static extern void ICertainInterface.Func(int cnt,[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)] ref string[] colors)

This may help you achieve the same, Dll import is usually used to call win api 这可能会帮助您达到相同的效果,Dll导入通常用于调用win api

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM