Retrieving COM Objects from Unmanaged Code

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

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

Here is a C ++ snippet that illustrates what I do 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 this with C ++ / CLI,” although I'm not sure how to do this for any generic type, and how I will force raw IUnknown pointers to manager pointer types that I would declare using [Guid] on a managed interface.

+3
source share
1 answer

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

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

Then, if you have an object in managed code. Cast is the equivalent of QueryInterface

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

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

I would suggest that you change the factory prototype from

IUnknown * GetFactory();

to

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

It seems that the COM iterop code has a strong assumption that all COM methods return HRESULT, and it will be easier to get marshalling to work if you go there with a stream.

+1
source

Source: https://habr.com/ru/post/1730505/


All Articles