COM即组件对象模型,是Component Object Model
COM是一种跨应用和语言共享二进制代码的方法。与C++不同,它提倡源代码重用。ATL便是一个很好的例证。源码级重用虽然好,但只能用于C++。它还带来了名字冲突的可能性,更不用说不断拷贝重用代码而导致工程膨胀和臃肿。
COM通过定义二进制标准解决了这些问题,即COM明确指出二进制模块(DLLs和EXEs)必须被编译成与指定的结构匹配。这个标准也确切规定了在内存中如何组织COM对象。COM定义的二进制标准还必须独立于任何编程语言(如C++中的命名修饰)。一旦满足了这些条件,就可以轻松地从任何编程语言中存取这些模块。由编译器负责所产生的二进制代码与标准兼容。这样使后来的人就能更容易地使用这些二进制代码。
最简单的一种COM服务器,进程内服务器(in-process)。“进程内”意思是服务器被加载到客户端程序的进程空间。进程内服务器都是DLLs,并且与客户端程序同在一台计算机上。进程内服务器在被COM库使用之前必须满足两个条件或标准:
- 必须正确在注册表的HKEY_CLASSES_ROOT\CLSID 键值下注册;
- 必须输出DllGetClassObject()函数;
这是进程内服务器运行的最小需求。在注册表的HKEY_CLASSES_ROOT\CLSID 键值下必须创建一个键值,用服务器的GUID作为键名字,这个键值必须包含两个键值清单,一是服务器的位置,二是服务器的线程模型。 COM库对 DllGetClassObject() 函数进行调用是在CoCreateInstance() API中完成的。
还有三个函数通常也要输出:
- DllCanUnloadNow():由COM库调用来检查是否服务器被从内存中卸载;
- DllRegisterServer():由类似RegSvr32的安装实用程序调用来注册服务器;
- DllUnregisterServer():由卸载实用程序调用来删除由DllRegisterServer()创建的注册表入口;
extern UINT g_uDllRefCount; // 服务器的引用计数
COM类的构造函数g_uDllRefCount++,析构函数g_uDllRefCount--
UINT m_uRefCount; // com对象的引用计数
AddRef()时m_uRefCount++,Release()时m_uRefCount--
COM对象在请求接受时QueryInterface() 函数内部如果成功应自动调用AddRef();