您的位置:首页 > 其它

COM创建机制(二)

2014-07-25 09:27 134 查看
一、类厂

客户程序并不直接调用组件程序的引出函数,而是直接调用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,所以该函数无法创建远程机器上的对象,如果要创建远程对象,可以使用CoCreateInstanceEx
if(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,组件程序为进程内组件程序,使用前必须先注册,注册方法在第一章中已经说过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  COM