Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pass a struct between .NET and C++ using COM?

I'm hosting a .NET library in my C++ program using the following methods, though not an exhaustive list:

CorBindToRuntimeEx()
GetDefaultDomain()
CreateInstance()
GetIDsOfNames()

And eventually a call to Invoke().

This works fine for basic types, enums, strings, and arrays. However, I cannot figure out how to pass a struct. Here's a skeleton of what I have now:

//library.cs  
public class AStruct
{
    public int i1;
    public string s1;
    public double d1;
}  

//...
public AStruct getAStruct();

//interop.cpp  
HRESULT hr = assembly->Invoke (id_getAStruct, ...);

The OUT PARAM return value of this function is a VARIANT with type VT_DISPATCH.

When I view retVal.pdispVal in my debugger, I can see that the contents of my struct are not near that address. I'd like to use varIDis.pdispVal->QueryInterface() to access my struct, but I have no idea what the IID is, nor how to discover it.

Also, I don't have the source code to the .NET library, though I can see much of it with Reflector. I'm using a test library I wrote in .NET to figure out how to proceed.

So, how can I pass and receive structs between .NET and C++ using COM?

Thanks greatly.

like image 912
David Avatar asked Nov 29 '25 03:11

David


1 Answers

I don't think your problem is related to structs. In fact, there are no structs involved here - not in C#, nor C++ nor COM. The getAStruct method (of some unspecified class?) returns a pointer to the IDispatch interface on an instance of the AStruct class.

You don't have enough hard information to do things properly, so this is how I'd approach it... (lots of guessing...)

Forget structs. You're stuck with an IDispatch*. If you know the full definition of the AStruct class, or at least the full list of its properties and the order they're defined in, then start with this assumption: the DISPID of the first property is 0x6002000. The next is 0x6002001, and so on. This isn't guaranteed, of course, but you might be lucky. And I forget the conditions that cause the DISPIDs to start at 0x60020000, so it might be totally wrong. Also, I don't suppose there's any guarantee that the properties' DISPIDs go in the same order as their definitions in the source code.

Moving breezily along, call IDispatch::Invoke on the IDispatch* you've got, passing the guessed DISPIDs and wFlags=DISPATCH_PROPERTYGET/PUT.

Like I said, lots of guessing. But if my back was against the wall, this is where I'd start.

like image 90
Ciaran Keating Avatar answered Nov 30 '25 18:11

Ciaran Keating