组件对象模型

组件对象模型（英語：Component Object Model，縮寫COM）是微軟的一套软件组件的二进制接口标准。这使得跨编程语言的进程间通信、动态对象创建成为可能。COM是多项微软技术与框架的基础，包括OLE、OLE自动化（英语：OLE Automation）、ActiveX、COM+、DCOM、Windows shell、DirectX、Windows Runtime。COM與實作語言種類無關，如此使用它實作的物件可用在不同於開發它的環境，甚至跨越機器邊界。對製作良好的物件，COM使物件得以重複使用，而無須知道其內部實作，因為它強制實作者提供與實作分離、確切定義的介面。各語言不同的儲存配置語意使组件对象模型用物件參照計數(Reference counting)管理其自身的產生與銷毀。不同介面間型別轉換的鑄型用 QueryInterface 方法。 COM的核心是一组组件对象间交互的规范，定义了组件对象如何与其使用者通过二进制接口标准进行交互，COM的接口是组件的类型纽带。 除了规范之外，COM还是一个称为“COM库”的实现，包括若干API函数，用于COM程序的创建与使用。 COM还提供定位服务的实现，可以根据Windows系统注册表，从一个类标识（CLSID）来确定组件的位置。 COM采用自己的IDL来描述组件的接口（interface），支持多接口，解决版本兼容问题。COM为所有组件定义了一个共同的父接口IUnknown。GUID 是一个 128 位整数（16 字节），COM将其用于计算机和网络的唯一标识符。 除了基本规范和系统实现之外，COM的构成还包括永久存储、绰号（moniker智能命名/标记）和统一数据转移（UDT = Uniform Data Transfer）三个核心的操作系统部件。 COM实质上是一种语言无关的对象实现方式，这使其可以在创建环境不同的场合、甚至跨计算机的分布环境下被复用。COM允许复用这些对象，而不必知道对象内部是如何实现，因为组件实现者必须提供良好定义的接口从而屏蔽实现细节。通过引用计数，组件对象自己负责动态创建与销毁，从而屏蔽了不同编程语言之间的内存分配语义差异。在COM接口之间的类型转换通过QueryInterface方法。 对于某些应用程序来说，COM已经部分被.NET框架取代。COM通过Windows Communication Foundation（WCF）支持Web Service。COM对象通过.NET COM Interop可以被所有.NET语言使用。网络化的DCOM使用二进制私有格式，而WCF鼓励使用基于XML的SOAP消息机制。COM非常类似其他软件组件接口技术，如CORBA与JavaBeans，它们各自有其优点与弱点。 与C++不同，COM提供了一个稳定的应用二进制接口（ABI），不随编译器版本而改变 。 早在1988年，微软的Anthony Williams的论文“Object Architecture: Dealing with the Unknown or Type Safety in a Dynamically Extensible Class”以及1990年的“On Inheritance: What It Means and How To Use it”论文奠定了COM的理论基础。 Windows作業系統提供了三種进程間的通訊機制：剪貼簿、DDE與OLE。OLE原名是物件連結與嵌入（Object Linking and Embedding），OLE可以說是DDE的改良版。1992年，OLE 1.0版随Windows 3.1操作系统发布，提供复合文档（compound document）处理，但它過於複雜，Brockschmidt, Kraig的「Inside OLE」一书中提到，必须经过六个月的心灵混沌期，才能了解OLE是什么。1993年，COM架构随OLE 2.0第一次公开发布。在微软Office套件中，COM取代了OLE。这成为COM技术战胜Windows 95团队开发的其他对象技术的关键因素。 1996年，为应对CORBA，DCOM随Windows NT 4 Option Pack发布。 1999年，Windows 2000发布了COM+，关注MTS，并放弃了DCOM这个名称。 COM是基於元件物件方式概念來設計的，在基礎中，至少要讓每個元件都可以支援二個功能： 查詢元件中有哪些接口 讓元件做自我生命管理，此概念的實踐即為引用計數（Reference Counting） 這二個功能即為COM的根：IUnknown介面所提供的IUnknown::QueryInterface()，IUnknown::AddRef()及IUnknown::Release()三個方法的由來。所有的COM元件都要實作IUnknown，表示每個COM元件都有相同的能力。 只由COM衍生實作出來的元件，稱為純COM元件。 但在Windows持續發展時，Visual Basic 4.0開始支援OCX，也就是OLE Custom Control，這讓微軟開始思考要如何讓COM元件可以跨語言支援，在這樣的要求下，必須要提供一個一致的介面，以及提供一組可以呼叫介面內方法的能力，由於純COM元件只能夠支援C/C++的直接存取，為了要達到跨語言的能力，在COM中必須要支援在外部呼叫內部方法的機能，這個機能造就了Invoke()方法，另外為了跨語言的支援，COM應該要提供簡單的元件存取識別方式，這也就是會有GetIDsOfNames()的原因，將這些方法組合起來，定義出的必要介面，稱為IDispatch介面，所有實作此介面的，都可以支援跨語言的支援。 微軟將實作此介面的元件都稱為自動化（Automation）元件。 COM曾是Windows平台下主要的軟體開發平台，並且影響至其他許多相關軟體技術。 COM+是微軟Windows 2000中，Microsoft Transaction Server的強化實作版本，除了提供基本的元件交易支援外，還提供了鬆散藕合式事件（loosely-coupled events）與物件共用池（object pooling）等應用程式伺服器的能力，成為Windows 2000開始在微軟平台上主要的應用程式伺服器平台，目前.NET Framework也提供了System.EnterpriseServices命名空間以支援COM+。 Distributed COM是依據遠程過程調用（RPC，Remote Procedure Call）的規範發展的可以在網路上通訊的COM元件，它將COM元件的能力擴及到網路上，但因為網路安全以及防火牆因素，DCOM無法廣泛的流行。 .NET Framework是新一代的Microsoft Windows應用程式開發平台。使用C#开发COM組件，首先創建类型为Class Library的项目，然后在项目的Property中进入Build页，对“Register for COM interop”选项打勾。打开AssemblyInfo.cs文件，设置[assembly: ComVisible(true)]，这样就可以生成.tlb文件。源程序示例如下： using System.Runtime.InteropServices; namespace MyNameSpace { //可以通过//菜单“工具/guid 生成”。 [Guid("298D881C-E2A3-4638-B872-73EADE25511C")] public interface AddComInterface { [DispId(1)] int iadd(int a, int b); [DispId(2)] string stradd(string strA, string strB); } [Guid("2C5B7580-4038-4d90-BABD-8B83FCE5A467")] [ClassInterface(ClassInterfaceType.None)] public class AddComService : AddComInterface { public AddComService() { } public int iadd(int a, int b) { int c = a + b; return c; } public string stradd(string strA, string strB) { return strA+strB ; } } } 不同的COM组件类型用类ID（CLSID）标示，这是一种全局唯一标识符（GUID）。每个COM组件用一个或多个接口来暴露其功能。这些接口也采用GUID唯一标识，称为接口ID（IID）。 COM接口与几种编程语言有语言绑定，如C语言、C++、Visual Basic、Delphi语言、Python以及Windows平台上的几种脚本语言。它们都是通过接口的方法来访问组件。 所有COM组件都实现了IUnknown接口，该接口暴露了引用计数实现的对象生命期管理与类型转换，以访问不同的预定义接口。 IUnknown接口以及基于IUnknown的定制接口包括一个指向虚函数表（英语：virtual method table）的指针，虚函数表中包含若干函数指针，分别指向接口所声明的函数实现。对于进程内的COM组件调用，其效率等同于C++的虚函数调用。 除了基于IUnknown的定制接口，COM也支持继承自IDispatch的dispatch接口，从而支持了用于OLE自动化（英语：OLE Automation）的晚绑定（英语：late binding）。不能访问定制接口的编程语言（例如VBS）可以通过dispatch接口访问COM组件。 Windows API提供了C语言定义COM接口的方法： #include <objbase.h> #undef INTERFACE #define INTERFACE IClassFactory DECLARE_INTERFACE_(IClassFactory, IUnknown) { // *** IUnknown methods *** STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE; STDMETHOD_(ULONG,AddRef) (THIS) PURE; STDMETHOD_(ULONG,Release) (THIS) PURE; // *** IClassFactory methods *** STDMETHOD(CreateInstance) (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppvObject) PURE; }; // 等效的C++例子: struct FAR IClassFactory : public IUnknown { virtual HRESULT STDMETHODCALLTYPE QueryInterface( IID FAR& riid, LPVOID FAR* ppvObj) = 0; virtual HRESULT STDMETHODCALLTYPE AddRef(void) = 0; virtual HRESULT STDMETHODCALLTYPE Release(void) = 0; virtual HRESULT STDMETHODCALLTYPE CreateInstance( LPUNKNOWN pUnkOuter, IID FAR& riid, LPVOID FAR* ppvObject) = 0; }; // C语言宏扩展后是这样的: typedef struct IClassFactory { const struct IClassFactoryVtbl FAR* lpVtbl; } IClassFactory; typedef struct IClassFactoryVtbl IClassFactoryVtbl; struct IClassFactoryVtbl { HRESULT (STDMETHODCALLTYPE * QueryInterface) ( IClassFactory FAR* This, IID FAR* riid, LPVOID FAR* ppvObj) ; HRESULT (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ; HRESULT (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ; HRESULT (STDMETHODCALLTYPE * CreateInstance) ( IClassFactory FAR* This, LPUNKNOWN pUnkOuter, IID FAR* riid, LPVOID FAR* ppvObject); HRESULT (STDMETHODCALLTYPE * LockServer) ( IClassFactory FAR* This, BOOL fLock); }; COM类（coclass）是一个或多个接口的具体实现，它很类似面向对象程序设计语言中的类。类的GUID标识被称作类ID（CLSID）；或者programmatic identifier字符串（progid），因为VBS等脚本语言不能使用GUID，只能用字符串查找、使用COM组件。 COM对象不能被直接访问，只能通过COM接口来访问对象。COM也支持同一个接口的多个实现，因此客户程序运行时可以选择实例化接口的哪个实现。 类型库（type library）包含着COM类型的元数据。这些类型采用微软接口定义语言（MIDL）描述。 IDL文件定义了类、接口、结构、枚举与其他用户定义类型。IDL类似于C++的声明，使用了一些额外的关键字如interface、library等。IDL还支持在声明前给出方括號属性（bracketed attribute）以提供额外信息，如接口的GUID、指针参数与长度域之间的关系等。 MIDL编译器用来编译IDL文件，产生编译器独立的头文件。头文件包含了IDL文件中声明的接口对应的结构定义。结构只包含一项成员，即指向在接口中声明函数的地址表的指针（vtbl），以模仿C++对虚函数的实现。头文件还包含了类与接口等的GUID的常量的定义。MIDL编译器也可以产生C++源文件，包含代理模块（proxy module），用以把COM调用转为远程过程调用，以支持跨进程的DCOM通信。 IDL文件也可以被MIDL编译器生成类型库（TLB）文件.TLB，以供其他语言编译器与运行时环境使用，如VB、Delphi、.NET等生成语言相关表示COM类型的结构。C++把TLB转回到IDL表示。 使用C++的预编译directive#import ，可以装入如下格式的类型信息： 包含类型库的文件，如.olb、.tlb、.dll等； progid libid exe文件 dll文件包含着类库资源（如.ocx） 复合文档包含了类库 其他可以被LoadTypeLib函数理解的文件 #import创建两个头文件以用C++源码形式恢复类型库信息： 类型库主头文件（.TLH）：类似于MIDL编译器产生的头文件，还有一些额外的代码与数据； 类型库次头文件（.TLI）：编译器产生的成员函数。该文件被包含在主头文件中。 两个文件被放在输出目录中。编译器在现场就地#include主头文件。 类型库主头文件（.TLH）包含七部分： 头部常规代码 将要用到的结构的前向引用与typedef 智能指针声明：使用宏语句_COM_SMARTPTR_TYPEDEF建立了COM接口的typedef，实际上是_com_ptr_t的模板特化。 Typeinfo声明：类定义、ITypeLib:GetTypeInfo返回的其他Typeinfo项 可选的旧格式的GUID常量定义，形如CLSID_CoClass、IID_Interface #include类型库次头文件 尾部常规代码：#pragma pack(pop) 从第2至第6部分都包含在命名空间中，其名字在最初的IDL文件的library语句中给出。改名字在#import语句中可用属性no_namespace抑制掉；也可用rename_namespace属性更名。 COM是一个运行时框架，类型必须在运行时单独地标识并可指定。为此，使用GUID，每个COM类型被指定了它自己的GUID用于运行时标识。这也解决了C/C++语言的名字修饰导致的链接兼容性问题。 为了使COM类型信息在编译时与运行时都可以访问，COM使用类型库。这使得COM成为对象交互的动态框架。 考虑下述用IDL定义coclass的例子： coclass SomeClass { [default] interface ISomeInterface; }; 上述代码框架声明了一个COM类，称为SomeClass，实现了接口ISomeInterface。 这在概念是等价于下述C++类： class SomeClass : public ISomeInterface { ... ... }; 其中ISomeInterface是一个C++虚基类。 包含COM接口与类的IDL文件被编译为类型库（TLB）文件。客户程序可以在运行时分析类型库文件，以确定对象支持哪些接口，然后调用对象的接口方法。 C/C++程序以类ID（CLSID）与接口ID（IID）作为参数，用CoCreateInstance函数实例化COM对象。SomeClass的实例化代码如下： ISomeInterface* interface_ptr = NULL HRESULT hr = CoCreateInstance(CLSID_SomeClass, NULL, CLSCTX_ALL, IID_ISomeInterface, (void**)&interface_ptr); 在这个例子中，使用COM子系统获取指向ISomeInterface接口的实现对象的指针，用CLSID_SomeClass指示用这个特定的coclass。 所有COM对象采用引用计数管理对象的生命期。客户程序通过所有COM对象都要强制实现的IUnknown接口的AddRef与Release方法来控制引用计数。当引用计数降到0时，COM对象自己负责释放内存。即对动态分配内存创建的COM对象，其Release函数内部引用计数降为0时，就释放自身所占的动态分配内存。有的COM对象（如IClassFactory）往往是静态对象，Release函数内部引用计数降为0时不需做额外的操作。 特定语言（例如Visual Basic）提供了自动引用计数，所以COM对象开发者在源代码中不需要显式维护任何内部的引用计数。C/C++编程者或者执行显式的引用计数，或者使用智能指针（如MFC提供的CComPtr）自动管理引用计数[需要解释]。 下述是如何调用COM对象的AddRef与Release的指引： 函数、方法返回接口的引用（通过返回值或者"out"参数），应当在返回前增加被返回的对象的引用计数。 接口指针被覆盖或超出作用域之前，必须调用接口指针的Release方法。 如果一个接口引用指针被复制，必须调用该指针的AddRef方法。 AddRef与Release必须在被引用的相关接口上调用。因为一个COM对象可能实现了逐个接口上的引用计数，使得仅在相关接口上内部分配资源。 不向远程对象发出引用计数的调用。代理模块保持着远程对象的一个引用，并维持着它自己的本地引用计数。 为简化COM开发，引入了活动模板库（Active Template Library，ATL）用于C++开发。ATL提供了更高层次的COM开发范式。ATL也有益于COM客户应用程序开发摆脱直接维护引用计数，而是用智能指针对象。 其他能直接支持COM的库与语言还包括MFC Visual C++编译器的COM支持、VBScript、Visual Basic、ECMAScript（JavaScript）和Borland Delphi等。 COM是一个语言独立的二进制标准，任何能够理解与实现COM的二进制定义的数据类型与接口的语言都可以开发COM组件。 COM实现负责进入、离开COM环境，实例化与引用计数COM对象，查询对象支持的接口，以及错误处理。 Microsoft Visual C++编译器支持对C++语言的扩展：称作C++ Attributes。这些扩展被设计用于简化COM开发，去除实现COM服务器时大量臃肿的代码。 在Windows操作系统中，COM类、接口、类型库都会根据其GUID登记到Windows注册表。HKEY_CLASSES_ROOT\CLSID下是COM类；HKEY_CLASSES_ROOT\Interface下是接口。COM类型库注册在每个COM对象的本地库条目下或者远程服务的网络位置处。 不使用注册表的COM（RegFree COM）是Windows XP引入的技术，允许COM组件不在注册表中存期激活的元数据与类ID（CLSID），而是在实现类的assembly manifest（英语：Manifest (CLI)）或者存储在可执行文件的资源中或组件安装时的单独文件中。这使得同一组件的不同版本可以安装在不同目录下，用其各自的manifest描述，直接复制安装（英语：XCOPY deployment）。这种技术有限支持EXE COM服务器且不能用于系统范围组件如MDAC、MSXML、DirectX或Internet Explorer。 应用程序装入时，Windows装入器搜索manifest。如果存在，装入器从它增加信息到激活上下文。COM类工厂试图实例化一个类时，激活上下文首先检查这个CLSID的实现是否可以找到。仅当查找失败时，才扫描Windows注册表。 COM对象可以透明地实例化与引用在同一进程、跨进程边界、甚至在网上远程（DCOM）。进程外或远程对象用marshalling序列化方法调用与返回值。这种marshalling对用户是不可见的，就如同访问进程内的COM对象。 一个进程加载了一个COM的DLL文件后，该DLL可能定义并使用了一些可修改的全局变量或访问共享资源。该进程内的多个线程如何并发访问该DLL并保证是线程安全的，这就是“套间”（apartment）技术需要解决的问题。 COM对象与创建或调用COM对象的线程可以按两种策略来实现并发安全： 按照单线程执行方式写COM对象的代码，完全不考虑并发执行问题。这样的每个COM对象只能由一个线程执行，该线程通过Windows消息队列实现多线程访问该COM对象被串行化从而并发安全。这种策略称作单线程套间（Single-Threaded Apartment，STA）。 COM对象的代码自身实现了并发控制（通过Windows互斥原语，如互斥锁、临界区、事件、信号量等）。因此实际上多线程可以直接调用该COM对象的方法，这是并发安全的。这种策略称作多线程套间（Multi-Threaded Apartment，MTA）。 COM的并发安全的具体实现，提出了套间（apartment）概念。每一种套间类型表示在一个进程内部是多线程情况下，如何同步对COM对象的调用。套间是一个逻辑容器，收纳遵循相同线程访问规则的COM对象与COM线程（创建了COM对象的线程或者调用了COM对象的方法的线程）。套间本质上只是一个逻辑概念而非物理实体，没有句柄类型可以引用它，更没有可调用的API操纵它。套间有两种： 单线程套间（Single-Threaded Apartment，STA）：每个进程可以有多个STA套间。每个STA套间只能有一个线程。每个STA性质的COM对象只能属于一个STA套间。一个STA套间可以有零个或多个STA属性的COM对象，这些COM对象的方法只能由该套间的唯一线程执行。STA套间的线程可以直接调用该套间的COM对象的方法。如果STA套间的COM对象被套间外的线程或进程调用，那么该套间的线程必须实现Windows消息队列与消息循环处理机制，其他线程必须通过marshalling与unmarshalling机制，通过给该STA套间的线程发送Windows消息来调用COM对象。每个STA性质的线程自动形成一个STA套间，这个套间容纳了该线程及其创建的所有STA性质COM对象。MTA性质的线程创建STA性质的COM对象时，系统自动把该COM对象放在default STA套间内，由该套间的STA线程来执行该COM对象的方法。每个进程至多有一个default STA套间，该套间与套间内线程是自动生成的。 多线程套间（Multi-Threaded Apartment，MTA）：每个进程至多有一个MTA套间。所有MTA性质的线程都属于MTA套间。所有MTA性质的COM对象也都属于这个MTA套间。STA性质的线程创建MTA性质的COM对象时，系统自动创建一些线程以执行这些MTA性质的COM对象，这些线程也属于MTA套间，系统返回安整后的COM对象的描述给STA性质的线程。 中立套间（Thread Neutral Apartment，NA）：一个进程可以有一个中立套间。中立套间只包含COM对象，不包含线程。当STA或MTA线程调用同一进程的NA对象，则调用线程临时离开它的套间并执行COM对象的代码，没有任何线程切换。即任何线程都可以直接了当调用COM对象的方法。因此NA可以认为是优化套间之间方法调用的效率。 一个COM对象只能存在于一个套间。COM对象一经创建就确定所属套间，并且直到销毁它一直存在于这个套间。COM对象的套间类型写在Windows注册表相关条目中。 一个COM线程从创建到结束都属于同一个套间。COM线程只有两种套间模式：STA或MTA。线程必须通过调用CoInitializeEx()函数并且设定参数为COINIT_APARTMENTTHREADED或者COINIT_MULTITHREADED，来指明该线程的套间模式。调用了CoInitializeEx()函数的线程即已进入套间，直到线程调用CoUninitialize()函数或者自身终止，才会离开套间。COM为每个STA的线程自动创建了一个隐藏窗口，其Windows class是"OleMainThreadWndClass" 。跨套间调用这个STA套间内的COM对象，实际上是向这个隐藏窗口发送了一条窗口消息，通过消息循环与分派，该窗口过程收到这条窗口消息并调用相应的COM对象的接口方法。 线程访问属于同一套间的COM对象，直接执行方法调用而不需COM设施的辅助。线程跨套间边界去调用COM对象，传递的指针需要marshalling。如果通过标准的COM的API来调用，可以自动完成安整。例如，把一个COM接口指针作为参数传递给另外一个套间的COM对象的proxy的情形。但如果软件编程者跨套间传递接口指针而没有使用标准COM机制，就需要手工完成安整（通过CoMarshalInterThreadInterfaceInStream函数）与反安整（通过CoGetInterfaceAndReleaseStream函数获取COM接口的proxy）。例如，把COM接口指针作为线程启动时的参数传递的情形。 跨进程的调用COM对象类似于同一进程内跨套间的调用COM对象。 COM对象coclass在注册表表示中的子键InProcServer32下的条目中ThreadingModel给出： STA初始化时，创建一个隐藏窗口，用于apartment之间、进程间的消息路由。该窗口必须有正常的消息队列泵。这种结构称为消息泵。早期版本的Windows，消息泵的失败会导致系统范围的死锁。这个问题被初始化COM的Windows API复杂化了，并会导致实现细节的泄露。 如果多个对象是循環參照（Circular reference），则可能会导致问题。 Objects may also be left with active reference counts if the 使用COM事件池（event sink）模型，则对象可能一直保持活动的引用计数而不能被销毁。因为发送事件的对象必须有处理事件的对象的引用，因而对象引用计数永远不为0. 引用循环可以采取下述技术来克服： 带外终止（out-of-band termination），对象暴露一个方法，该方法调用时迫使该对象放弃对其他对象的全部引用。 身份分离（split identity）技术，一个实现暴露两个单独的COM对象（也称作identity），之间保持weak reference。 进程内的COM组件是用DLL文件实现，每个版本的DLL用CLSID登记到Windows注册表，因而某些情况下会发生DLL Hell效应。无需注册的COM克服了这一问题。 COM组件间的约定，纯粹是通过用户与组件之间的语义保证和假设的形式来表示的。COM用类型的形式表示组件约定。但是该约定存在如下两个关键问题，使得其对语义的表示并不是最优的。 约定的描述：COM没有定义约定的交换格式，即COM规范所约定的类型定义，必须通过完全是COM之外的某种技术来进行交互。微软定义和支持的COM交换格式有两个——IDL（Interface Definition Language接口语言定义）和TLB（Type LiBrary类型库），但是这两种格式并不是同构的，其中也没有哪种格式是权威的或标准的。 COM缺乏对组件依赖性的描述。因此，没有办法来解析COM组件（或者其约定的定义），也不能确定它所需要（依赖）的其他组件与版本。 COM约定的描述格式缺乏扩展性。IDL是基于文本的，极少随组件部署，通常只有C++程序员才会使用。TLB在扩展性方面存在缺陷，VB不使用TLB。 约定的工作方式是基于类型描述的，所采用的类型系统是C++的可移植子集。而且COM对组件的约定是物理的二进制约定，要求每个方法都具有精确的虚函数表偏移量、每个被传递的参数在堆栈规则中都有明确的偏移量、对象引用采用接口指针的明确格式、使用规定的分配器进行被调用这内存分配。COM组件的约定的精确性，产生了高效的代码；但不可靠性、开发使用及扩展升级的困难与复杂性高昂。 可移植对象（英语：Portable object (computing)），跨语言跨平台对象模型定义 Distributed COM（DCOM），使COM能在网络中工作的扩展 通用语言架构，当前的.NET跨语言跨平台对象模型 Windows Runtime，应用程序模型，指向Windows 8的COM演进版本 CORBA，通用对象请求代理体系结构，开放式跨平台对象模型 D-Bus，开放跨语言跨平台对象模型 KDE Frameworks 5 KDE组件框架 SOM（英语：IBM System Object Model），IBM系统对象模型，功能丰富的COM替代品 XPCOM，Mozilla应用程序跨平台组件对象模型 JavaBeans Java远程方法调用 ICE (中间件) 綁紮 Foreign function interface（英语：Foreign function interface） 调用约定 名字修饰 应用程序接口 - API 应用二进制接口 - ABI SWIG，开源自动接口绑定生成器，从许多语言到其他语言 搜索术语. Microsoft. [2015-04-22]. （原始内容存档于2016-03-06） （中文（简体））.  搜尋詞彙. Microsoft. [2015-04-22]. （原始内容存档于2016-03-06） （中文（繁體））.  "COM (DCOM) Team won 2011 Outstanding Technical Achievement in Microsoft". [2016-12-27]. （原始内容存档于2017-01-18）.  存档副本. [2014-06-07]. （原始内容存档于2020-05-15）.  存档副本. [2014-06-07]. （原始内容存档于2021-04-23）.  Compiler COM Support. MSDN. Microsoft. [2014-06-07]. （原始内容存档于2018-09-24）.  Microsoft MSDN: C++ Attributes Reference （页面存档备份，存于互联网档案馆） MSDN Magazine: C++ Attributes: Make COM Programming a Breeze with New Feature in Visual Studio .NET （页面存档备份，存于互联网档案馆） Assembly Manifests. MSDN. [2009-11-05]. （原始内容存档于2018-05-10）.  Dave Templin. Simplify App Deployment with ClickOnce and Registration-Free COM. MSDN Magazine. [2008-04-22]. （原始内容存档于2015-04-11）.  How to use an out-of-process COM server without its tlb file. [2011-04-16]. （原始内容存档于2020-08-10）.  Concepts of Isolated Applications and Side-by-side Assemblies. MSDN. [2009-11-05]. （原始内容存档于2010-03-05）.  Codeguru: Understanding COM Apartments （页面存档备份，存于互联网档案馆） Microsoft MSDN: Processes, Threads, and Apartments （页面存档备份，存于互联网档案馆） Microsoft MSDN: Single-Threaded Apartments （页面存档备份，存于互联网档案馆） Microsoft MSDN: Multithreaded Apartments （页面存档备份，存于互联网档案馆） Microsoft MSDN: Understanding and Using COM Threading Models （页面存档备份，存于互联网档案馆） COM: A Brief Introduction (powerpoint). [March 7, 2006]. （原始内容存档于2007-11-29）.  Box, Don. Essential COM. Addison-Wesley. 1998. ISBN 0-201-63446-5.  Chappell, David. Understanding ActiveX and OLE. Microsoft Press. 1996. ISBN 978-1-57231-216-6.  Integration and Migration of COM+ services to WCF. [April 15, 2010]. （原始内容存档于2018-09-07）.  Microsoft COM Technologies （页面存档备份，存于互联网档案馆） Interview with Tony Williams, Co-Inventor of COM （页面存档备份，存于互联网档案馆）（Video Webcast, August 2006） A concise technical overview of COM （页面存档备份，存于互联网档案馆） from master's thesis Info: Difference Between OLE Controls and ActiveX Controls （页面存档备份，存于互联网档案馆） from Microsoft TypeLib Data Format Specification (unofficial) （页面存档备份，存于互联网档案馆） with open source dumper utility. The COM / DCOM Glossary