3

I’m trying to retrieve an array of structures through a COM interface. It works when the number of structures is 1. When the number of structures is greater than 1, only the first structure is marshaled correctly. The remaining structures in the array have garbage data. My interface looks like this:

typedef struct tagINTOBJINTERFACE
{
    long lObjectId;
    IMyObject* pObj;

} INTOBJINTERFACE;


[
    object,
    uuid(<removed>),
    dual,
    nonextensible,
    helpstring("Interface"),
    pointer_default(unique)
]
interface IMyInterface : IUnknown {

    HRESULT CreateObjects(
        [in] VARIANT* pvDataStream,
        [out]long* Count, 
        [out,size_is(,*Count)] INTOBJINTERFACE** ppStruct
        );
};

I allocate the structure memory like this:

long lCountInterfaces = listInterfaces.GetCount();
long lMemSize = lCountInterfaces * sizeof(INTOBJINTERFACE);
INTOBJINTERFACE* pstruct = (INTOBJINTERFACE*) CoTaskMemAlloc( lMemSize );

And then fill in the members of each structure in the array. I can see in the debugger that all members of all array elements are properly assigned. After filling in the structures, I assign “*ppStruct = pstruct” to pass the array out. I can also see that the out parameter “*Count” is properly set to the correct number of elements.

Why doesn’t this work?

Ken
  • 427
  • 4
  • 20

2 Answers2

6

Reason: Your application uses the universal marshaller from windows for mashalling. The universal marshaller reads the meta data from your typelib (*.tlb).
The generated typelib doesn't support size_is.

Todo: You should use the Proxy/Stub dll generated by Visual Studio (...PS project). - Build the Proxy/Stub dll - call "regsvr32 " - remove the "TypeLib = s '{?????-...-????}'" entry from your servers "*.rgs" file

Joerg
  • 61
  • 1
  • 2
0

In addition to Joerg's answer that using size_is is not possible, here is what's possible: SAFEARRAY.

Keywords: Safearray of UDT

Explanation and examples are here

Short summary:

  1. Define structure with a GUID.
  2. Create object of type IRecordInfo that describes your structure using the type library.
  3. Use SafeArrayCreateEx to create SAFEARRAY of type VT_RECORD.
  4. Fill it with data.
  5. Retrieve on the other side.
vt.
  • 1,325
  • 12
  • 27