早就想学习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组件对象的自注册功能。