1、 CoGetClassObject
函数原型:
HRESULT CoGetClassObject(const CLSID& clsid, DWORD dwClsContext, COSERVERINFO* pServerInfo, const IID& iid, (void **)ppv);
参数说明:
clsid: 指定COM类厂的CLSID标识符;
dwClsContext: 指定组件类别(进程内、进程外组件等等);
pServerInfo: DCOM留用;
iid: 接口IClassFactory的标识符IID_IClassFactory;
ppv: 存放类厂对象的接口指针;
2、 DllGetClassObject
函数定义:
HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, (void **)ppv)
{
if(clsid == CLSID_Dictionary)
{
CDictionaryFactory* pFactory = new CDictionaryFactory;
if(pFactory == NULL)
{
return E_OUTOFMEMORY;
}
HRESULT result = pFactory->QueryInterface(iid, ppv);
return result;
}
else
{
Return CLASS_E_CLASSNOTAVAILABLE;
}
}
参数说明:
clsid: 待创建对象的CLSID标识符;
iid: 指定接口IID;
ppv: 存放类厂对象的接口指针;
3、CoCreateInstance
函数定义:
HRESULT CoCrateInstance(const CLSID& clsid, IUnknown* pUnknownOuter, DWORD dwClsContext, const IID& iid, (void **)ppv)
{
IClassFactory* pCF;
HRESULT hr;
hr = CoGetClassObject(clsid, dwClsContext, NULL, IID_IClassFactory, (void *)pCF);
if(FAILED(hr)) return hr;
hr = pCF->CreateInstance(pUnkOuter, iid, (void **)ppv);
pCF->Release();
return hr;
}
参数说明:
clsid: 待创建对象的CLSID标识符;
pUnknownOuter: 用于对象被聚合的情形;
dwClsContext: 指定组件类别(进程内、进程外组件等等);
iid: 指定接口IID;
ppv: 存放类厂对象的接口指针;
4、 CoCreateInstanceEx
函数定义:
HRESULT CoCreateInstaceEx(const CLSID& clsid, IUnknown* pUnknownOuter, DWORD dwClsContext, COSEVERINFO* pServerInfo, DWord dwCount, MULTI_QI* rgMultiQI);
参数说明:
clsid: 待创建对象的CLSID标识符;
pUnknownOuter: 用于对象被聚合的情形;
dwClsContext: 指定组件类别(进程内、进程外组件等等);
pServerInfo: 指定服务器信息;
dwCount: 与rgMultiQI指定一个结构数组,用于保存多个对象接口指针;
rgMultiQI: 同上;
5、 CreateInstance(类厂函数)
函数定义:
HRESULT CrateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv)
{
CDictComp *pObj;
HRESULT hr = E_OUTOFMEMORY;
*ppv = NULL;
if(pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION;
}
pObj = new CDictComp();
if(pObj == NULL)
{
return hr;
}
hr = pObj->QueryInterface(iid, ppv);
if(hr != S_OK)
{
g_DictionaryNumber--;
delete pObj;
}
return hr;
}
参数说明:
clsid: 待创建对象的CLSID标识符;
pUnknownOuter: 用于对象被聚合的情形;
dwClsContext: 指定组件类别(进程内、进程外组件等等);
iid: 指定接口IID;
ppv: 存放类厂对象的接口指针;
6、 IClassFactory
接口原型:
Class IClassFactory : public IUnknown
{
Virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, (void **)ppv) = 0;
Virtual HRESULT __stdcall LockServer(BOOL bLock) = 0;
};
参数说明:
pUnknownOuter: 用于对象被聚合的情形;
iid: 指定接口IID;
ppv: 存放类厂对象的接口指针;
bLock: 加锁或解锁;
7、 创建对象三种方法
(1)、CoCreateInstance (最常用的方法)
(2)、CoGetClassObject (希望获取类厂对象(的函数))
(3)、CoCreateInstanceEx (创建远程对象或一次获取对象多个接口指针)
8、一般创建流程
.
(1). CoCreateInstance调用CoGetClassObject函数;
(2). COM库找到DLL程序并进入进程;
(3). 调用DLLGetClassObject函数;
(4). DLLGetClassObject函数创建类厂;
(5). DllGetClassObject函数把类厂接口指针返回给CoGetClassObject函数;
(6). CoGetClassObject函数把类厂接口指针返回给CoCrateInstance函数;
(7). CoCreateInstance函数得到类厂后,调用类厂的对象创建函数;
(8). 类厂创建COM对象;
(9). 类厂把COM对象返回给CoCreateInstance函数,CoCreateInstance函数返回;
(10). 客户直接调用COM对象。
9、“客户程序—COM库—组件程序(DLL)”协作过程分析
客户程序 | COM库 | 组件程序(DLL) |
CLSID clsid; IClassFactory* pClf; IUnknown* pUnknown; CoInitialize(NULL); CLSIDFromProgID(“Dictionary.Object”, &clsid); |
|
|
| COM在注册表中查找字典CLSID |
|
CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, IDD_IClassFactory, (void **)&pClf); |
|
|
| COM库在内存中查找clsid组件 if(DictComp.dll还没有被装入内存) { 从注册表中获取组件程序全 路径名”…/DictComp.dll”; CoLoadLibrary(); } DllGetClassObject(clsid, IDD_IClassFactory, &pClf); |
|
|
| 创建类厂对象CDictionaryFactory, 并返回IClassFactory接口 |
| COM库返回IClassFactory接口给客户 |
|
pClf->CreateInstance(NULL,IDD_IUnknown,(void **)&pUnknown); |
|
|
|
| 类厂对象的CreateInstance函数被调用 (通过组件的vtable被客户直接调用) 用new操作符构造字典组件对象 new CDictionary, 并返回IUnknown接口指针 |
客户使用字典组件,通过其接口进行各种操作… pClf->Release(); pUnknown->Release(); |
|
|
|
| 组件对象的Release函数被调用 if(m_Ref == 0) { delete this; return 0; } |
CoFreeUnusedLibraries() |
|
|
| COM库调用字典组件的引出函数DllCanUnloadNow() |
|
|
| DllCanUnloadNow函数中: if(不存在字典对象 && 锁计数为0) return TRUE; else return FALSE: |
| if(组件DllCanUnloadNow()返回TRUE) { CoFreeLibrary(…); } |
|
CoUninitialize() |
|
|
| COM库释放资源 |
|
客户程序退出 |
|
|
10、组件生存期管理