在最简单的形式中,COM 只是vtable
二进制合约加上所有接口之母:IUnknown
. COM 是一种无需源代码即可重用代码的方法,使用组件,它是某种动态转换机制。如果我知道你支持的类(它们的CLSID
)、它们公开的接口(它们的IID
),以及这些接口的方法布局、它们的参数、顺序、类型等,我可以使用你的 COM 服务器。
但是为了简化 COM 客户端和 COM 服务器之间的“通信”,您可以/应该使用一些标准机制/文档并添加工具,以便无需任何努力即可处理诸如编组(=序列化)之类的管道工作。这在进程外的情况下至关重要,对进程内的情况不太重要(我将在这里避开“公寓”的概念......)
所以,你会在 COM 中找到的很多东西(如注册、工具、IDL、类型库等)实际上是可选的,但也非常有用(所以它们最终会成为强制性的)。(对于“接口语言定义”)之类的目的idl
是定义并向您的 COM 客户端公开您的 COM 服务器支持的内容,以便工具可以为您和您的客户端自动生成大量代码(.c、.h、.tlb )。请注意,如果没有在 idl 中定义它们,没有什么可以阻止您实现接口或 coclass。没有任何义务要求您提供 .idl 或 .tlb。在这种情况下,只有知道它们的 IID、方法布局等,我才能使用它们。
然后,在 之上IUnknown
,微软创建了一个通用接口IDispatch
(这也称为“自动化”,或“后期绑定”,而不是“早期绑定” IUnknown
),当时针对 VB/VBA 客户端(甚至在 VBScript 之前, JScript 和许多其他 COM 客户端,.NET 支持 IUnknown 和 IDispatch)。IDispatch
,如果你走那条路,可能是你必须实现的最后一个接口,因为它的语义允许完全发现和调用任何方法,只要它支持一组有限的已定义数据类型,即“自动化类型”:BSTR ,变体等。
所以,如果你支持IDispatch
,提供一个 TLB(类型库)并将所有类型限制为自动化类型,那么你不需要处理封送处理,你不需要代理和存根,你可以忘记这一切,即使在输出-进程方案,因为 Microsoft 会自动实现这一点。过去,我们曾经将“oleaut32.dll”称为“通用编组器”。
双接口是同时支持IUnknown
和派生的接口IDispatch
。它们的存在主要是为了同时支持 C/C++ 客户端和自动化客户端。在 C/C++ 中使用自动化(BSTR、VARIANT 等)有点痛苦,因为它们最初不打算由 C/C++ 客户端使用……注意微软提出了 C++ 智能包装类:CComBSTR
and CComVARIANT
with ATL,或_variant_t
and _bstr_t
with Windows SDK。