I have a c++ method which creates, fills and returns SAFEARRAY:
SAFEARRAY* TestClass::GetResult(long& size)
{
return GetSafeArrayList(size);
}
How should I export that function in a DLL so that c# could take it
How should I write c# method signature?
I have in c++ something along these lines:
extern "C" __declspec(dllexport) void GetResult(SAFEARRAY*& data, long& size)
{
size = 0;
data = handle->GetResult(size);
}
Is it correct, isn't it?
Thanks for help!
EDIT:
c# call:
public static extern void GetResult(IntPtr handle, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_USERDEFINED)] TestStruct[] data, ref int size);
Full example of use of a
SAFEARRAY(int)
C#->C++->C# (so the array is initialized with some data in C#, passed to C++, modified there and returned to C#).C++:
C#
and
Code partially taken from https://stackoverflow.com/a/12484259/613130 and https://stackoverflow.com/a/3735438/613130
SAFEARRAY(VT_RECORD)
It is doable... Very hard... but doable. Please don't do it. You can't hate enough the world to do it. I do hope you don't!
C++:
C#:
and
There is a single big caveat for
GetResultSafeArray
: you must pass from C# at least an empty array (like anew ManagedUDT[0]
). This because to create aSAFEARRAY(ManagedUDT)
from nothing in C++ you would need aIRecordInfo
object. I don't know how to retrieve it from C++. If you already have aSAFEARRAY(ManagedUDT)
then clearly it has theIRecordInfo
already set, so there is no problem. In the example given, in C++ there are first some sanity checks, then the passed array is printed, then it is emptied, then it is re-filled. TheGetResultSafeArrayOut
/GetResultSafeArrayRef
"cheat": they receive from C# aITypeInfo
pointer (that is easy to retrieve in C#, withMarshal.GetITypeInfoForType()
), and from taht the C++ can retrieve theIRecordInfo
interface.Some notes:
I wrote Ansi-charset-C++. Normally for myself I always write Unicode-ready C++ (or directy Unicode-C++, because all the Windows NT support Unicode), but I've noticed that I'm an exception... So in various parts of the code there are conversions BSTR->Ansi->BSTR.
I'm retrieving the
HRESULT
of all the function calls. They should be checked, and the failure handled.The most complex thing in C++/COM is knowing when to free something... In general always free/
Release()
everything! (be itBSTR
/IUnknown
derived interfaces, ...)Unless there is a bug, there is no support for this code. Consider it to be a proof of concept. I already lost various hours on it out of curiosity. You break it, you repair it.