在客戶端需要調用COM組件時,通常調用windowAPI函數:
STDAPI CoCreateInstance(
REFCLSID rclsid, //創建的Com對象的類標識符(CLSID)
LPUNKNOWN pUnkOuter, //指向接口IUnknown的
指針
DWORD dwClsContext, //運行
可執行代碼的上下文
REFIID riid, //創建的Com對象的接口
標識符
LPVOID * ppv //用來接收指向Com對象接口地址的
指針變量
);
來返回所需函數的接口ppv。其實這個函數是一個封裝函數,共封裝了創建COM對象的兩個步驟。
一、類工廠
類工廠(IClassFactory),是用來生成類對象實例(即給類分配內存)並返回所請求接口(上面的ppv參數)的一個類。
COM組件中的類與類工廠是分離的。從本質上講,類工廠類生育了我們所需要的那個類。
如何辦到的呢?
類工廠有個函數 HRESULT CreateInstance(LPUNKNOWN pUnk,REFIID riid,void** ppv),該函數傳入所需要的類的那個接口的IID(riid),並返回那個接口ppv.
在這個函數內部,所需類是通過new函數直接創建的,然后調用這個類的QuryInterface()函數返回那個接口ppv的。
因此,最終類還是通過new函數創建的,只是把這個過程隱藏了,不對客戶公開。
二、DllGetClassObject函數
該函數用來創建類工廠實例,並返回類工廠接口指針。通過這個指針調用CreateInstance()就實現了獲取所需接口的指針。
STDAPI DllGetClassObject(REFCLSID rclsid,REFIID riid, LPOVID* ppv)
rclsid:組件的GUID
riid:類工廠的GUID
ppv:類工廠的接口指針
因此總的順序就是:
CoCreateInstance調用CoGetClassObject()加載COM組件,后者調用DllGetClassObject(clsid,id_ifactory,ppv_factory)生成類工廠指針,類工廠指針再調用CreateInstance()生成類實例,返回接口指針。
至於為什么要通過類工廠創建組件對象實例,原因有二:
1.類工廠創建對象是對對象創建過程的一種統一封裝,實現不同語言創建COM組件統一性。
2.COM對象可以位於客戶進程之外。
至於接口和類之間是怎樣一一映射的,可能是通過他們的GUID建立起來的映射關系。因為類也有自己的GUID,因此類工廠只提供了接口的GUID,但是還是能夠實例化接口對應的類。