1. COM程式設計基礎
COM是一種規範,而不是實作。
當使用C++來實作時,COM元件就是一個C++類,而COM接口就是繼承至IUnknown的純虛類,COM元件就是實作相應COM接口的C++類。
COM規範規定,任何元件或接口都必須從IUnknown接口中繼承而來。IUnknown定義了3個重要函數,分别是QueryInterface、AddRef和Release。其中,QueryInterface負責元件對象上的接口查詢,AddRef用于增加引用計數,Release用于減少引用計數。引用計數是COM中的一個非常重要的概念,它很好地解決了元件對象地生命周期問題,即COM元件何時被銷毀,以及誰來銷毀地問題。
除了IUnknown接口外,還有另外一個重要地接口,即IClassFactory。COM元件實際上是一個C++類,對于元件地外部使用者來說,這個類名一般不可知,那麼如何建立這個類地的例?由誰來建立?COM規範規定,每個元件都必須實作一個與之對應的類工廠(Class Factory)。類工廠也是一個COM元件,它實作了IClassFactory接口。在IClassFactory的接口函數CreateInstance中,才能使用new操作生成一個COM元件類對象執行個體。
COM元件有3種類型:
① 程序内元件(CLSCTX_INPROC_SERVER)
② 本地程序元件(CLSCTX_LOCAL_SERVER)
③ 遠端元件(CLSCTX_REMOTE_SERVER)
在接口成員函數中,字元串變量必須用Unicode字元指針,這是COM規範的要求。
2. COM元件開發
實作一個COM元件,需要完成以下工作:
COM元件接口
COM元件實作類
COM元件建立工廠
COM元件注冊與取消注冊
本文以一個例子作為說明,COM元件提供了一個SayHello的接口函數,将“Hello COM”列印輸出。
2.1 建立COM元件接口
COM元件接口是一個繼承IUnknown的抽象類:
COM元件類是一個實作了相應COM元件接口的C++類,注意:一個COM元件可以同時實作多個COM接口。
2.3 COM元件建立工廠
對于元件地外部使用者來說,這個COM元件的類名一般不可知,那麼如何建立這個類地執行個體?由誰來建立?COM規範規定,每個元件都必須實作一個與之對應的類工廠(Class Factory)。類工廠也是一個COM元件,它實作了IClassFactory接口。在IClassFactory的接口函數CreateInstance中,才能使用new操作生成一個COM元件類對象執行個體。
2.4 COM元件的注冊
COM元件需要使用regsvr32工具注冊到系統才能被調用,然而COM元件是如何被regsvr32注冊的?一個典型的自注冊COM元件需要提供4個必需的導出函數:
DllGetClassObject:用于獲得類工廠指針
DllCanUnloadNow:系統空閑時會調用這個函數,以确定是否可以解除安裝COM元件
DllRegisterServer:将COM元件注冊到系統資料庫中
DllUnregisterServer:删除系統資料庫中的COM元件的注冊資訊
DLL還有一個可選的入口函數DllMain,可用于初始化和釋放全局變量
DllMain:DLL的入口函數,在LoadLibrary和FreeLibrary時都會調用
導出檔案(Source.def):
生成完後,使用regsvr32注冊到系統中:
3. COM元件使用
COM元件的使用包括:
如何建立COM元件
如何得到元件對象上的接口以及如何調用接口方法
如何管理元件對象(需熟悉COM的引用計數機制)
下面的代碼是最一般的步驟:
下面我們編寫一個用戶端,調用之前寫的COM元件服務:
上面的例子和一般步驟不一緻,少了QueryInterface,是因為預設傳回的就是指定的接口,下面按一般步驟再實作一次:
是直接建立COM元件并擷取接口,還是先建立COM元件得到預設接口再查詢其他的接口,需要具體問題具體分析。
4.COM元件運作機制
一個COM元件從編寫到最終可以被調用,整個運作流程是怎樣的?或者我們再考慮簡單一點,COM元件是如何被調用的?