早就想學習COM方面的技術了,可是水平有限,看了老長時間還是連最基本都看不懂,最近發現了一本DirectShow方面的書,看到關於COM的一些基本的知識,講的也不多,看了看覺得挺好,還可以理解,遂寫下了筆記。
先寫一下虛擬碼,然後再作分析。
CoInitalize(NULL); //COM初始化
IUnknow *pUnk = NULL;
IObject *pObject = NULL;
//建立組建對象
HRESULT hr = CoCreateInstance(CLSID_Object,CLSCTX_INPROC_SERVER,NULL,IID_IUnknow,(void**)&pUnk);
if(SUCCEEDED(hr))
{//查詢得到組建對象上的介面
hr = pUnk->QueryInterface(IID_Iobject,(void**)&pobject);
if(SUCCEEDED(hr))
{//調用介面方法
pobject->SomeMethod();
pobject->Release();
}
pUnk->Release();
}
CoUninitialize();//釋放COM使用的資源
//CoCreateInstance() 函數
CoCreateInstance(...)
{
IClassFactory *pclassFactory = NULL;
CoGetclassObject (CLSID_Object,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(void**)&pClassFactory);
pClassFactory->CreateInstance(NULL,IID_IUnknow,(void**)pUnk);
pClassFactory0>Release();
}
CoGetClassObject函數
CoGetClassObject(...)
{
//通過查詢註冊表CLSID_Object得到組建DLL檔案路徑
//裝入DLL庫(調用LoadLibrary)
//使用函數GetProcAddress(...)得到DLL中函數DLLGetClassObject的函數指標
//調用DLLGetClassObject得到類工廠對象指標
}
DLLGetClassObject函數
DLLGetClassObject(...)
{
//建立類工廠
CFactory *pFactory = new CFactory;
//查詢得到IClassFactory指標
pFactory->QueryInterface(IID_IClassFactory,(void**)&pClassFactory);
pFactory->Release();
}
CreateInstace函數
CFactory :: CreateInstance(...)
{
//建立CLSID_Object對應的組建對象
CObject *pObject = NEW CObject;
pObject->QueryInterface(IID_IUnknow,(void**)&PUnk);
pObject->Release();
}
現在來瞭解一下COM的基本知識:
COM使用C++來實現時,COM組件就是一個C++類,而介面都是純虛類。
CLASS Ifunction
{
public:
virtual Method1(...) = 0;
virtual Method2(...) = 0;
};
class myobject : public Ifunction
{
public:
virtual Method1(...) {...};
virtual Method2(...) {...};
};
Ifunction就是介面,而Myobject就是COM組件。
COM規範規定:任何組件或介面都必須從IUnknow介面中繼承而來,IUnknown定義了幾個重要函數,分別是QueryInterface、AddRef和Release。其中QueryInterface負責組件對象上介面的查詢,AddRef用於增加引用計數,Release用於減少引用計數。
除了IUnknown介面外,還有一個介面:IClassFactory。COM組件實際上是一個C++類,對於組件外部使用者來說,類名一般不可知,那麼該如何建立類的執行個體?由誰來建立?
COM規範規定,每個組件都必須實現一個與之相對應的類工廠(class Factory)。類工廠也是一個COM組件,它實現了IClassFactory介面。在IClassFactory介面函數CreateInstance中,才能使用New操作產生一個COM組件類對象執行個體。
每個COM組件都使用一個GUID來惟一標識。當建立一個COM組件時,總是首先通過這個GUID(例CLSID_Object)調用CoGetclassobject來獲得建立這個組件對象的類工廠,然後調用類工廠介面方法。
IClassFactory::CreateInstance.就能真正建立CLSID_Object標識的組件對象了。
COM規範 Exports
DllGetclassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
其中DllGetclassObject在建立對象的時候被調用,根據CLSID返回對應的類工廠對象,DllCanUnLoadNow用於判斷是否可以從記憶體中卸載DLL,即DLL中實現的所有COM對象是否都已釋放;DLLRegisterServer和DllUnregisterServer完成COM組件對象的自註冊功能。