Unmanaged Code和Managed Code混合编程中使用COM接口指针的一种方法
大家先看一段代码。
private unsafe void Initialize(IDispatch* pObject)
{
this.m_pdispObject = pObject;
**(((int*) pObject))[4](pObject);
this.m_eventIID = Guid.Empty;
this.m_dwEventCookie = 0;
}
{
this.m_pdispObject = pObject;
**(((int*) pObject))[4](pObject);
this.m_eventIID = Guid.Empty;
this.m_dwEventCookie = 0;
}
这是使用C#语言写的某Class的一个成员函数内的部分代码。
其中 **(((int*) pObject))[4](pObject); 这一行是关键的一笔,初看起来,很像是早期使用C语言写OLE程序时的情景,至少有异曲同工的感觉。
要理解这一行代码的意思,需要看一下在上下文中IDispatch的定义:
[StructLayout(LayoutKind.Sequential, Size=4), MiscellaneousBits(0x41), DebugInfoInPDB, NativeCppClass, CLSCompliant(false)]
public static class IDispatch : ValueType
{
}
public static class IDispatch : ValueType
{
}
这又是在C#语言中定义对应于C++ Class的Object的VPtr的一种非常妙的方法。
至此,就可以完全清楚前面那段代码的意思了:
**(((int*) pObject))[4](pObject);
这一行相当于C++中的
pObject->AddRef();
至于"[]"操作符中,为什么是4代表了AddRef调用,留给读者自己去理解,结合COM规范中接口的本质、C++ Class的V-Table的布局,不难得到答案。
Unmanaged Code和Managed Code混合编程中,这种使用COM接口指针的方法,虽稍显晦涩,但在不方便使用C++/CLI而必须使用C#的地方,还是很方便的,而且整体来看,这种方式也还是相当优雅的。