COM SAFEARRAY GUID returns from C ++ to C #

I am currently facing the problem of passing SAFEARRAY (GUID) as the return value from C ++ to C #.

Currently, the C # side uses the Interop library created from Tlbimp.exe (Type library importer).

IDL:

HRESULT GetGuids( [out]SAFEARRAY(GUID)* guids); 

I also tried [out, retval]

Function Signature:

 HRESULT WINAPI MyClass::GetGuids(SAFEARRAY** guids) 

If I use SafeArrayCreate() or SafeArrayCreateVector() :

 SAFEARRAY* psa psa = SafeArrayCreate(VT_CLSID, 1, rgsabound); 

I get a NULL SAFEARRAY pointer, which should indicate an invalid E_OUTOFMEMORY .

I found that VT_CLSID is only for Ole property sets, not SAFEARRAY: http://poi.apache.org/apidocs/org/apache/poi/hpsf/Variant.html It states that CLSID

I also tried alternative means of building a safe array with: SafeArrayAllocDescriptor() and SafeArrayAllocData() .

 hResult = SafeArrayAllocDescriptor(1, guids) hResult = SafeArrayAllocData(*guids); 

This allows me to create an array, but when filling it with SafeArrayPutElement() I get HRESULT 0x80070057 (parameter is incorrect). This is probably due to the fact that it accepts the VT_CLSID parameter, as well as

I can fill it manually with SafeArrayAccessData()

 GUID* pData = NULL; hResult = SafeArrayAccessData(*guids, (void**)&pData); 

but I get an error from C #: "The value does not fall into the expected range"

I'm not sure how to accomplish the desired SAFEARRAY (GUID) return functionality in C # with either the retval or out parameter.

It seems to be simple - there are many areas in the IDL where I already pass the GUID without UDT or sorting. Everything works fine until I need to pass them to SAFEARRAY.

Any help is appreciated, thanks in advance

+4
source share
2 answers

You are absolutely right - the problem is that VT_CLSID is not allowed in either VARIANT or SAFEARRAY. This boils down to the fact that the GUID is not an Automation compatible type.

I often need to do the same thing that you are trying. The easiest way to solve the problem is to convert the GUID to a string and then pass SAFEARRAY (VT_BSTR). It is a bit contrary to the texture to do this conversion, but I suppose you could assume that marshaling is happening anyway, and this transformation is a type of marshaling.

+3
source

A way to do this involves passing the GUID as a UDT (user-defined type).

To do this, we use SAFEARRAY from VT_RECORD elements that will be initialized using SafeArrayCreateEx. But first, we need to get a pointer to IRecordInfo, which can describe the type.

Since the GUID is defined in the Windows / COM headers and uuid is not connected to it, we must use something else to get the IRecordInfo interface. Basically, two options are to create a structure that has the same memory layout as the GUID in your own TypeLib, or uses mscorlib :: Guid defined in mscorlib.tlb

 #import <mscorlib.tlb> no_namespace named_guids IRecordInfo* pRecordInfo = NULL; GetRecordInfoFromGuids( LIBID_mscorlib, 1, 0, 0, __uuidof(Guid), &pRecordInfo ); SafeArrayCreateEx( VT_RECORD, 1, &sab, pRecordInfo ); 
+2
source

All Articles