COM创建机制(二)

来源:互联网 发布:淘宝做单一个月挣多少 编辑:程序博客网 时间:2024/05/16 07:30

一、类厂

客户程序并不直接调用组件程序的引出函数,而是直接调用COM库的函数进行组件对象的创建工作。COM库的创建函数根据注册表的信息调用组件程序的标准入口函数(DLLGetObjectClass)来创建组件对象.

COM对象大概创建过程如下:


类厂:

类厂就是COM类的工厂,确切地讲,类厂应该称为“对象厂”,是COM对象的生产基地,COM库通过类厂创建COM对象,每一个COM类,有一个类厂专门用于该COM类的对象创建操作。类厂本身也是一个COM对象,它支持一个特殊的接口IClassFactory。COM规定第一个COM对象类都应该有一个相应的类厂对象,由组件程序的引出函数DllGetClassObject调用。

 IClassFactory : public IUnknown    {    public:
//创建对应的COM对象        virtual /* [local] */ HRESULT STDMETHODCALLTYPE CreateInstance(             /* [unique][in] */ IUnknown *pUnkOuter,    //用于对象被聚合的情形,一般设为NULL            /* [in] */ REFIID riid,     //对象创建完成后,客户应该得到的初始化接口IID            /* [iid_is][out] */ void **ppvObject) = 0; //存放返回的接口指针        //控制组件对象的生命周期        virtual /* [local] */ HRESULT STDMETHODCALLTYPE LockServer(             /* [in] */ BOOL fLock) = 0;            };
COM对象的创建

创建COM对象有三个COM库函数,分别为:CoGetClassObject , CoCreateInstance , CoCreateInstanceEx

__checkReturn WINOLEAPI  CoGetClassObject(__in REFCLSID rclsid, //COM类ID
__in DWORD dwClsContext, //组件类别(进程内组件,进程外组件或者进程外控制对象)
__in COSERVERINFO *pServerInfo,//创建远程对象时指定服务器信息__in REFIID riid,//指定接口IID
__deref_out LPVOID FAR* ppv //存放类厂对象的接口指针
);
进程内组件对象的创建,函数CoGetClassObject调用DLL模块的DllGetClassObject引出函数,把参数clsid、iid、ppv传给DllGetClassObject,由该函数创建类厂对象,并返回类厂对象接口指针。

进程外组件对象的创建,首先CoGetClassObject函数启动组件进程,然后一直等待,直到组件进程把它支持的COM类对象的类厂注册到COM中(COM类的类厂对象通过CoRegisterClassObject),于是,CoGetClassObject函数把COM中相应的类厂信息返回。当进程退出时,必须调用CoRevokeClassObject函数以便通知COM它所注册的类厂对象不再有效,CoRegisterClassObject和CoRevokeClassObject必须成对出现,以保证COM信息的一致性。

__checkReturn WINOLEAPI CoCreateInstance(__in     REFCLSID rclsid,                            __in_opt LPUNKNOWN pUnkOuter,//主要用于被聚合情况                           __in     DWORD dwClsContext,                            __in     REFIID riid,                            __deref_out LPVOID FAR* ppv);

CoCreateInstance函数把通过类厂创建对象的过程封闭起来,客户程序只要指定对象类的CLSID和待输出的接口指针及接口IID,函数返回后,客户就可以得到对象的接口指针,使客户程序可以不再与类厂打交道

HRESUlT CoCreateInstance(const CLSID &clsid , iUnknow *pUnknownOuter , DWORD dwClsContext , const IID &iid , void ppv){IClassFactory *pCF;HRESULT hr;hr = CoGetClassOjbect(clsid ,dwClsContext,NULL , IID_IClassFactory , (void *)pCF);//创建类厂对象,因为第三个参数被指定为NULL,所以该函数无法创建远程机器上的对象,如果要创建远程对象,可以使用CoCreateInstanceExif(FAILED(HR))return hr;hr = pCF->CreateInstance(pUnkOuter , iid , (void *)ppv);//利用类厂对象得到真正的COM对象pCF->Release();return hr;}
CoCreateInstanceEx函数
__checkReturn WINOLEAPI CoCreateInstanceEx(    __in REFCLSID                      Clsid,    __in_opt IUnknown     *            punkOuter, // only relevant locally    __in DWORD                         dwClsCtx,    __in_opt COSERVERINFO *            pServerInfo,//用于指定服务器信息    //参数dwCount和pResults指定了一个结构数组,用于保存多个对象接口指针,其目的在于一次获取多个接口指针,以便减少客户程序与组件程序之间的频繁交互;    __in DWORD                         dwCount,    __inout_ecount(dwCount) MULTI_QI * pResults );
三个创建对象函数的使用原则

1. 如果创建远程对象或者希望一次获取对象的多个接口指针,可以选用CoCreateInstanceEx函数
2. 如果希望获取类厂对象或者要调用类厂的某些成员函数,则选用CoGetClassObject函数
3. 其他情况下,使用CoCreateInstance函数创建对象

对象的创建介绍完毕,具体代码参与《COM原理与应用》一文中第三章的具体实例。

实例于客户程序DictCtrl和组件程序DictComp组成,基中DictComp包含类厂对象Factory和组件对象DictComp,组件程序为进程内组件程序,使用前必须先注册,注册方法在第一章中已经说过。


0 0
原创粉丝点击