COM组件学习

来源:互联网 发布:生死狙击刷矩阵要多久 编辑:程序博客网 时间:2024/05/19 14:36

COM组件是以Win32动态链接库(dll)或可执行的形式发布的可执行代码组成的。动态链接库本身并不能满足对于组件架构的需求。为了满足这些需求。组件还必须是封装的。
com组件是完全与语言无关的。
com组件可以以二进制形式发布。
com组件不妨碍老客户情况下升级。
com并不是一种计算机语言。
将com与dll相提并论也是不合适的。实际上com使用了Dll来给组件提供动态链接的能力。
com具有一个被称作是com库的API,他提供的是对所有客户及组件都非常有用的组件管理服务。

com组件在C++中是用纯抽象基类实现的。
一个com组件可以提供多个接口。
一个C++类可以使用多继承来实现一个可以提供多个接口的com。

客户请求服务时,只能通过接口进行。每一个接口都是有一个128位的全局唯一标识符GUID来标识 。客户通过GUID获得接口的指针,在通过接口指针,客户就可以调用其他相应的成员函数。具体功能如何实现,则完全由对象的接口内部实现。

每一个对象也用一个128位的GUID来标识,称为CLSID(类ID),客户程序可以由CLSID来创建COM对象。

接口特点:
1、二进制特性;
2、接口不变性;
3、继承性(可扩展性);
4、多态性(运行过程的多态性)

COM定义的每一个接口都必须从IUnKnow继承过来。原因:IUnKnow接口提供了两个非常重要的特性: 生存期控制和接口查询。IUnKnow引入了“引用计数”方法,有效的控制对象的生存周期。

1、引用计数:
COM采用引用计数来解决内存管理问题,当客户程序得到一个对象接口指针,引用计数加1, 客户用完了接口指针,引用计数减1,引用计数为0时,COM对象从内存中清除。
实现引用计数
三种选择:
1. 设置一个针对整个组件全局的引用计数;
2. 为每个COM对象设置一个引用计数;
3. 为每个接口设置一个引用计数;
使用规则
1. 函数参数中使用接口指针变量;(根据入参,出参,出-入参)
根据参数情况分类:入参,不必调用addRef, Realease;
出参, 调用addRef,使引用计数加1;
出入参,参数被修改之前,对新的接口调用Realease使引用计数减1,参数被修改之后,对新的接口调用addRef,过程中没有修改则不调用任何函数。
2. 局部接口指针变量(不调用AddRef和Release,因为接口总是有效)
3. 全局接口指针变量(开始调用AddRef, 函数返回调用Release)
4. C++中类成员变量为接口指针变量(规则3类似)
5. 以上情形都不适合遵循以下一般规则:
1.顺序执行过程中,对接口指针赋值:调用AddRef
2.结束接口指针使用,调用Release

2、接口查询
一个com对象可以实现多个接口,可以进行查询
QueryInterface
IUnknown的一个成员函数QueryInterface,客户可以通过此函数来查询某个组件是否支持某个特定的接口。若支持QueryInterface将返回一个指向些接口的指针,不支持返回值将是一个错误代码。

QueryInterface 有两个参数,和一个HRESULT返回值
HRESULT __stdcall QueryInterface( REFIID riid, void ** ppvObject);
第一个参数:接口标识符(IID)
第二个参数:存放所请求接口指针的地址。
返回值:查询成功返回S_OK,如果不成功则返回相应错误码。

com库与类厂的交互
com库中, 有三个 API函数用于对象的创建;分别是CoGetClassObject, CoCreateInstance和CoCreateInstanceEx;
成对出现:
CoGetClassObject()
CoRevokeClassObject()

CoCreateInstance() 内部调用了CoGetClassObject;
CoUninitialize()

COM库:
1、初始化:
CoInitialize(IMalloc* pMalloc);
CoUnInitialize() //反初始化

组件对象创建机制
类厂(对象厂,COM对象的生产基地,COM库通过类厂创建COM对象,对应每一个COM类,有一个类厂专门用于COm对象的创建):
支持一个特殊接口:IClassFactory
定义如下:

成员函数 CreateInstance 用户创建COM对象, 每一个COM对象对应一个类厂。

类厂本身也是个COM对象,那么类厂有谁创建?答案是:DllGetClassObject引出函数。

COM库与类厂的交互:
COM库中有三个主要函数:CoGetClassObject, CoCreateInstance , CoCreateInstanceEx(用于创建远程对象).COM库与类厂通过这三个函数进行交互。
CoGetClassObject函数先找到CLSID指定的COM库的类厂,然后连接到类厂对象。
注:客户、COM库、组件dll、类厂、组件之间的交互过程
1. 客户首先调用COM库的CoCreateInstance函数来创建COM组件。
2. CoCreateInstance首先调用COM库的CoGetClassObject获取类厂。
3. 该函数具体是通过调用了组件DLL输出的DllGetClassObject来创建类厂。
4. DllGetClassObject通过new函数产生一个Cfactory的对象,并通过QueryInterface获取其接口指针(一般是IclassFactory指针)。
5. 返回到COM库的CoCreateInstance调用刚才获得的接口指针(IclassFactory,类厂)的CreateInstance函数。
6. 该函数new指定的组件类,通过QueryInterface获得指定的接口
7. CoCrateInstanse释放掉IclassFactory指针(通过Release),然后向客户程序返回获得的指针。
8. 可以在客户中使用获得的接口了。

0 0