简体   繁体   中英

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.

The interface which I want to call is defined like this:

C# interop interface definition:

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

C++ definition:

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. The 2nd parameter BSTR * colors suppose to stand for the 1st string address in my string array.

Now this is the code I used to call up the interface from my C# application:

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#. 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.

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.)

Further more, I did a same test in excel VBA code which called the same interface:

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.

Now I totally have no idea how to fix this in my C# application. 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++; 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.

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

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

using DllImport attribute example

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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