COM 接口指针与实现 class 有何关系?

How do COM Interface pointers relate to the implementing class?

假设我有一个 COM 接口指针

IMyInterface *pInterface = 0x12696340;

我可以通过函数调用从调试器中看到这必须由 CMyImplementer 实现,但是 class 位于 0x12686e50。

我的问题是,COM 如何将接口与实现相关联class?必须有某种方法可以将接口转换为 class 指针 - 如何做到这一点?

COM一般不需要接口指针指向同一个物理对象;这完全取决于每个特定 COM 对象的实现。但是,任何逻辑对象的 IUnknown 指针必须相等,并且作为 对象标识 。因此,当您需要检查身份时,您可以只 QueryInterface for IUnknown 并检查该指针。

这是我熟悉的一种实现方式。不确定这种布局有多普遍,但它可能会让您了解什么是可能的。

内存中 class 的布局,在 32 位模式下,如下所示:

[ (4 bytes) ptr to vtable for IUnknown ]
[ (4 bytes) ptr to vtable for IDispatch ]
[ (4 bytes) ptr to vtable for IMyInterface ]     <--- pInterface points to here
[ (....) member variables of the class implementing CoYourClass etc. ]

内存中的其他地方(class 的所有对象的一个​​实例):

[ (12 bytes) vtable for CoYourClass::IUnknown ]
[ (28 bytes) vtable for CoYourClass::IDispatch ]
[ (4*n bytes) vtable for CoYourClass::IMyInterface ]    <---- (*pInterface) points here

vtable 中的条目指向 thunk。当你调用pInterface->Foo();时,检索到Foo对应的vtable表项,这是一个thunk的代码地址。该 thunk 接收 pInterface 作为其 this 指针。 thunk 知道它是 CoYourClass class 中的 IMyInterface thunk,并且在这种情况下它减去 8 字节的固定偏移量以检索指向对象开头的指针。然后 thunk 调用您为实现 Foo 而编写的实际代码,将调整后的指针作为 this.

传递

OP 注意事项:您可以通过在调用对象时检查调试器中的内存和变量来弄清楚编译器使用的布局(如果调试器允许您从客户端代码进入服务器代码以进行 in-进程对象)