从非托管代码中获取COM对象

时间:2010-01-29 05:59:10

标签: c# com managed

我有一个库,它导出一个非托管的C例程,该例程返回指向基于COM IUnknown的对象的指针。 DLL未注册,也不是服务器。我想使用C#中的COM类型。

我已经为COM类型编写了C#接口。什么是调用LoadLibrary()和GetProcAddress()的C#等价物?我如何调用GetProcAddress()的结果,然后调用它来加载COM接口指针?

这是一段C ++片段,展示了我的目标:

// 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);

我的直觉说“用C ++ / CLI做”,虽然我不确定如何为任何泛型类型执行此操作,以及如何将原始IUnknown指针强制转换为管理器指针类型,我将使用[管理界面上的Guid]属性。

1 个答案:

答案 0 :(得分:1)

您只需使用互操作来描述您的GetFactory函数,就像这样

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

然后,在托管代码中拥有该对象。强制转换等同于QueryInterface

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

您需要将C ++接口定义复制为C#接口定义,可能需要使用[marshalas]属性。但既然你已经这样做了,其余的应该很容易。

我建议您从

更改工厂原型
IUnknown * GetFactory();

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

COM iterop代码似乎有一个强烈的假设,即所有COM方法都会返回HRESULT,如果你顺其自然,那么编组工作会更简单。