COM对象创建过程详细分析

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、组件生存期管理

展开阅读全文

没有更多推荐了,返回首页