I have a managed function with the following declaration (both interface and implementation):
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
String[] ManagedFunction()
{
String[] foo = new String[1];
foo[0] = "bar";
return foo;
}
There is also a native C++ interface with the same methods as the managed interface, inside of that interface, this method has the following declaration:
void ManagedFunction(SAFEARRAY* foo);
This function is called by native code in the following way:
void NativeFunction(ManagedBinding binding)
{
CComSafeArray<BSTR> cComSafeArray;
cComSafeArray.Create();
LPSAFEARRAY safeArray = cComSafeArray.Detach();
binding.comObject->ManagedFunction(safeArray);
}
I’m not sure what I’m doing wrong but after my managed function has been called, safeArray appears to have garbage values, somethings going wrong while marshalling the return value back to native code. Could someone with more experience than me with .Net interop please shed some light on this? Also, It might be relevant to mention that I haven’t had problems with returning ValueTypes from my managed function (boolean if you’re curious), something about returning a String array is messing things up. Thanks!
Well I finally got it to work. I created a managed representation of
SAFEARRAYcalledManagedSafeArray(stolen from here : http://social.msdn.microsoft.com/Forums/en-US/clr/thread/6641abfc-3a9c-4976-a523-43890b2b79a2/):I changed the signature of my method to:
Inside my method, I manually updated the
dataPtrfield by callingMarshal.AllocCoTaskMem(...)and then copied over the strings I wanted theSAFEARRAYto contain.I have no idea as to why the CLR wasn’t able to automatically marshal the parameters to and from native code and I’d still appreciate it if someone could try to explain that.