C# – Obtaining COM objects from unmanaged code

ccommanaged

I have a library that exports an unmanaged C routine that returns pointers to COM IUnknown-based objects. The DLL is not registered, and is not server. I would like to use the COM types from C#.

I have already written C# interfaces for the COM types. What is the C# equivalent of calling LoadLibrary() and GetProcAddress()? How would I call the result of GetProcAddress() and then call it to load a COM interface pointer?

Here is a snippet of C++ that illustrates what I am after:

// Assume I have previously declared IMyType
HANDLE mylib = ::LoadLibrary("myfakecom.dll");
IUnknown* (*GetterFunc) getter;
getter = (GetterFunc)::GetProcAddress(mylib, "GetFactory");
IUnknown *unk = getter();
IMyType *mytype = unk->QueryInterface(IID_MYTYPE);

My gut says "Do it with C++/CLI", though I am unsure of how I would do this for any generic type, and how I would coerce the raw IUnknown pointers into the manager pointer types I would declare using the [Guid] attributes on a managed interface.

Best Answer

You just need to use interop to describe your GetFactory function, something like this

[DllImport("myfakecom.dll")]
[return: MarshalAs(UnmanagedType.IUnknown)]
static extern object GetFactory();

Then once you have the object in managed code. A cast is the equivalent of QueryInterface

void Foo(Object unk)
{
    IMyType mytype = (IMyType)unk;
} 

You will need to duplicate your C++ interface definitions as C# interface definitions, possibly with [marshalas] attributes. But since you have already done that, the rest should be easy.

I would suggest that you change your factory prototype from

IUnknown * GetFactory();

to

HRESULT GetFactory([out] IUnknown ** ppunk);

There seems to be a strong assumption by the COM iterop code that all COM methods return HRESULT and it will be simpler to get the marshalling to work if you go with the flow there.

Related Topic