简体   繁体   中英

Can't get SAFEARRAY to work with Interop

I have an ATL COM Server, where the method for the interface is

STDMETHODIMP CWrapper::RUN(long iDataSize, SAFEARRAY** iData)

and the MIDL for this function looks like

[id(1), helpstring("method RUN")] HRESULT RUN([in] long nSize, [in, size_is(nSize)] SAFEARRAY(_MyDataType*)* iData);

I import the tlb from this project using tlbimp, so I can use native arrays. I then call it from C# as follows

 m_ServerWrapper.RUN(iInputs.Length,ref iInputs)

where Inputs is already allocated and filled with another COM object from inside my C# program. Now, when I call into the C++ wrapper, I have a BadPtr for my safearray and the call into a subsequent COM object from CWrapper::RUN fails with the array not making it to the final dll. It shows up as unallocated. Does anyone have any clue what I'm doing wrong? Thanks

EDIT: I should have stated that the array looks just fine in C#.

EDIT2: The debugger shows iData safearray of IDispatch* = 0x0000000 <Bad Ptr>, 5, 0x0000000 <Bad Ptr>({lpvtbl = 0xblahblah},... . So it looks like some of my information is getting there.

A normal C# array is not the same as a SAFEARRAY. I think you have to make your own:

[StructLayout(LayoutKind.Sequential)]
struct SafeArray
{
    public ushort   dimensions;  
    public ushort   features;    
    public uint     elementSize; 
    public uint     locks;       
    public IntPtr   dataPtr;     
    public uint     elementCount;
    public int      lowerBound;  
}

Then use Marshal.AllocCoTaskMem() to create the memory. Fill in all the data and then pass it.

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