tags:

views:

58

answers:

1

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.

+1  A: 

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.

John Knoeller
Awesome! I hadn't realized that the COM interop stuff was implemented in terms of the same P/Invoke marshalling types. Should've been obvious. Thanks.
Armentage
Okay, this all works for the situations where you have a specific DLL you are going to invoke out of; however, what if you want to invoke any DLL at runtime?
Armentage
@Armentage: I suggest you make a new question, I don't know the answer to that off the top of my head, but I'll bet someone here does.
John Knoeller