COM原理及应用----COM对象和接口
1、 COM对象的理解
COM对象类似于C++语言中类的概念类的每个实例代表一个CO M对象它也包括属性即状态和方法即操作 状态反映对象的存在方法就是接口 。
2、 COM对象的标识CLSID
GUI D是一个128位的随机数重复概率极低。它的值来源于两部分空间值网卡地址或随机数和时间值。
获得GUID值可以使用V C++提供的工具 GUIDGe n.exe和UUIDGe n.exe。或者使用CO M库的API函数CoCr eatGui d。
3、 COM对象与C++对象的比较
封装特性
在COM对象中数据是完全封装在对象内部外部不可能直接访问对象的数据属性。通过COM对象和客户程序提供的接口成员函数访问对象的属性。 COM对象的数据成员的封装性是以组件为最终边界的对于对象用户是完全透明的、不可见的而C++对象的封装特性只是语义上的封装对于对象用户是可见的。
COM对象将数据完全封装在对象的内部。C++对象的封装是在语义上的封装通过不同的数据类型实现数据的封装。
可重用性
COM对象的可重用性表现在COM对象的包容和聚合一个对象可以完全使用另一个对象的所有功能而C++对象的可重用性表现在C++类的继承性派生类可以调用其父类的非私有成员函数。
COM对象的多态性通过其接口体现 C++对象的多态性通过其虚函数体现。
4、 COM接口的作用和意义
COM规范的核心内容是关于接口的定义虽然COM本身并不复杂但是围绕CO M接口有很多内容值得仔细探讨包括接口的标识、接口函数的调用习惯、参数处理、接口与对象的关系以及接口与C/C++的关系、 COM接口多具有的特性等。
COM定义了一套完整的接口规范不仅可以弥补API作为组件接口的不足还从分发挥了组件对象的优势并实现了组件对象的多态性。
5、接口定义和标识
接口是包含了一组函数的数据结构通过这组数据结构客户代码可以调用组件对象的功能。客户程序使用一个接口数据结构的指针来调用接口成员函数。接口指针实际上又指向另一个指针这第二个指针指向一组函数指针即一组函数地址 成为接口函数表。接口函数表中每一项为4个字节的函数指针每个函数指针与对象的具体实现联系起来。
从技术上讲接口是包含了一组函数的数据结构通过这组数据结构客户代码可以调用组件对象的功能。
客户程序用一个指向接口函数结构的指针来调用接口成员函数。实际上接口指针指向另一个指针pVta ble。
接口函数表称为虚函数表Virtua lFuncti onTable 简称vtab le指向vtab le的指针为pVtabl e。对于一个接口来说它的虚函数表vtable是确定的。
6、接口设计的问题
在接口成员函数中字符串变量必须用Unic ode字符指针这是COM规范的要求。
COM API函数使用大多数语言惯用的_st dcall调用习惯。
用C语言定义COM接口需要有结构体struct定义其接口结构接口成员函数必须有一个this指针。
用C++语言定义CO M接口因为由C++语言clas s的实现机理可以看出 COM接口结构中的vta ble与cl ass的vt able 类的虚函数表完全一致因此用class描述COM接口是最方便的手段。此时接口成员函数隐藏了thi s指针。c las s型接口的说明要比stru ct型接口的说明简捷得多。
7、 COM接口与对象的联系
接口类只是一种描述并不提供具体的实现过程。如果COM对象要实现接口 则COM对象必须以某种方式把它自身与接口类联系起来然后把接口类的指针暴露给客户程序于是客户程序就可以调用对象的接口功能了。
用c las s型接口通过把接口指针this与对象数据绑定在一起的方法实现对CO M接口的支持比较直观、简捷易于理解。实际上也可以采用其他的方法来实现接口只要接口成员函数中thi s指针即接口指针与对象数据能建立确定的连接在接口成员函数中可以访问到对象数据即可。例如VC++的MFC库和ATLactive templa te librar y活动模板
库模板库分别采用了不同的机制来提供对COM接口的支持。
8、接口描述语言IDL
COM规范在采用O SF的DCE规范描述远程调用接口ID Linterf ace descri ption language 接口描述语言的基础上进行扩展形成了COM接口的描述语言。接口描述语言提供了一种不依赖于任何语言的接口描述方法 因此它可以成为组件程序和客户程序之间的共同语言。
COM规范使用的I DL接口描述语言不仅可用于定义COM接口 同时还定义了一些常用的数据类型也可以描述自定义的数据结构对于接口成员函数我们可以制定每个参数的类型、输入输出特性甚至支持可变长度的数组的描述。VC++提供了MID L工具可以把IDL接口描述文件编译成C/C++兼容的接口描述头文件.h。
9、接口的内存模型
COM对象往往有自己的属性数据它们反映对象的状态并用于区分不同的对象。对于有多个对象的客户数据属性是不能公用的。
10、接口的特点
二进制特性
接口不变性
继承性扩展性类似于C++中类的继承性接口也可以继承发展但方式不同。类继承不仅是说明继承也是实现继承 即派生类可以继承基类的函数实现而接口继承只是说明继承 即派生的接口只继承了基接口的成员函数说明而没有继承基接口的实现。类继承允许多重继承但接口继承只允许单继承。根据COM规范所有接口都必须从IUnknown派生可以直接派生也可以间接派生。但大多数都是直接派生。O LE系统中接口最后字母是“2”或“Ex”的标煤它是一个继承接口。
多态性 COM对象具有多态性其通过COM接口体现。
11、 IUnkno wn接口提供了两个非常重要的特性生存期控制使用引用计数和接口查询。
12、 IUnkno wn接口引用计数的设置层级
引用计数在组件一级实现则计数分辨率太粗选择全局变量 在对象一级实现恰好使用C++类的成员变量 在接口一级实现则计数分辨率太细使用类成员变量。
13、使用引用计数的规则
根据不同场合使用或者传递接口指针标量进行分类并给出相应的规则
1函数的参数中使用接口指针变量。
输入参数 由于输入参数由调用函数控制 因此被调用函数执行过程中接口指针一定保持有效 引用计数不需要改变。
输出参数输出参数是指在被调用函数执行过程中进行赋值的参数而且被调用函数并没有用到函数初始化传进来的值输出参数相当于函数的一个返回值。在C/C++语言中输出参数为一个指针变量COM中不使用引用变量 。因为输出参数相当于在被调用函数中生成了一个新的接口指针变量 因此在被调用函数返回之前对输出参数应 该调用Add Ref使接口引用计数增1。这条规则也适用于函数返回值为接口指针变量的情况。
输入输出参数在参数被修改之前对原来传进来的接口指针调用Relea se以使引用计数减1在参数被修改之后对新的接口指针变量调用A ddRef 以标记对新的接口指针的引用。如果在函数执行过程中参数没有被修改则不需要改变。
2局部接口指针变量 因为在局部函数块中接口指针总是有效的所以一个局部接口指针变量被赋了值并调用了接口成员函数 引用计数不需要改变。
3全局接口指针变量把全局接口指针变量作为输入参数传给某个函数之前应该调用AddRef以保证在函数调用中可以使用给接口指针变量 因为它是全局变量其他的函数有可能会调用Release函数。在函数返回之后应该调用R elease函数。
4C++中类成员变量为接口指针变量 因为对于类的作用域来讲成员变量相当于全局变量 因此适用于规则3。
5当以上情形都不适合时使用以下一般的规则
在顺序执行过程中如果要对一个接口指针变量赋值则对赋值后的接口指针变量 调用AddR ef并且如果赋值前的接口指针变量还没有结束则赋值前必须对它调用Re lease以便先结束它的使用。
如果要结束使用一个接口指针变量 以后不再用到它了则调用Rel ease函数。
14、接口查询
使用Quer yInter face函数查询接口其返回值有S_OK、 E_NOIN TERFAC E、 E_UNEXPECTED。
15、 COM对象的接口原则
1对于同一个对象的不同接口指针查询得到的I Unknow n接口必须完全相同。即每个对象的IUnkno wn接口指针是唯一的。
2接口对称性。即对一个接口查询其自身总应该成功。
3接口自反性。
4接口传递性。
5接口查询时间无关性。
16、多接口COM对象的实现方法
在C++语言中有两种实现方法一是使用多重继承把所支持的接口作为其基类然后在对象类中实现接口成员函数二是使用内嵌接口类成员。
COM Objects and Interfaces
一个对象实现一个接口他的意思就是该对象使用代码实现了接口的每个方法
并且为这些函数通向com库提供了co m的二进制指针。然后com使这些函数运行在
请求了一个指向该接口的任何客户端。
Interfaces and Interface Implementations
COM在接口的定义和实现上有根本的差别。一个接口实际上是由一组定义了用法的相联系的函数原型组成只是他不能够被实现。这些函数原型就相当于C++中含有纯虚拟函数的基类。一个接口定义制定了接口的成员函数、调用方法、返回类型、他们的参数的数量和类型这些函数要干什么。但是这里并没有与接口实现相关的东西。这些函数的具体“代码”在“底层” 即COM对象中 即这些函数功能由COM组件实现。
一个接口的实现就是程序员在一个接口定义上提供的执行相关动作的代码。客户调用完全是决定于接口的定义。
Interface Pointers and Interfaces
接口实现的一个实例实际上就是一个指向一组方法的指针 即是指指向一个接口的函数表该函数表引用了该接口所有方法的实现。
每个接口是一个固定的一组方法的集合在运行时通过global ly unique interf aceidenti fier (IID)来定位。这里 IID是co m支持的gl obally unique identi fier(GUID)的特殊的实例。这样做就不会产生单一系统上相同名字、接口的多个版本的COM之间的冲突了。
一个COM接口与C++类是不一样的
一个COM接口不是一个对象——他只是简单的关联一组函数是客户和程序之间通信的二进制标准。只要它提供了指向接口方法的指针这个对象就可以用任何语言 来实现它。
COM接口是强类型的——每个接口有他自己的接口标识符
· COM接口的不变性——你不能够用老版本的接口标识符定义新的版本接口的IID定义的接口合同是明确的、唯一的。
IUnknown and Interface Inheritance
继承在COM里并不意味着代码的重用。因为接口没有实现关联接口继承并不意味着代码继承。他的意思仅仅是一个接口同一个合同关联就像C++的纯虚拟基类的创建和修改样可以添加方法或者更进一步的加强方法的使用。在COM里没有选择性继承。如果一个接口由另一个接口继承的话他就包含了另一个接口定义的所有的方法。
Using and Implementing IUnkno wn
COM为实现和使用对象和对象的内部通信提供了一个丰富的标准集合。对IUnkn own接口的实现和使用的细节请参见下面主题QueryI nterfa ce:Naviga ting in an Object 。Rules for Implementing QueryInterfac e
管理实现一个COM对象的IUnkno wn::QueryI nterfa ce方法的三个主要规则
1对象必须要有一个标识符
2一个对象实例的接口集合必须是静态的static
3在对象中从任何一个其他的接口查询此接口都应该成功。
通过引用计数来管理对象的生命周期
使用AddRe f //增加引用
Realas e //减少引用
Nocser刚刚在WHT发布了几款促销服务器,Intel Xeon X3430,8GB内存,1TB HDD,30M不限流量,月付$60.00。Nocser是一家注册于马来西亚的主机商,主要经营虚拟主机、VPS和马来西亚独立服务器业务,数据中心位于马来西亚AIMS机房,线路方面,AIMS到国内电信一般,绕日本NTT;联通和移动比较友好,联通走新加坡,移动走香港,延迟都在100左右。促销马来西亚服务器...
趣米云早期为做技术起家,为3家IDC提供技术服务2年多,目前商家在售的服务有香港vps、香港独立服务器、香港站群服务器等,线路方面都是目前最优质的CN2,直连大陆,延时非常低,适合做站,目前商家正在做七月优惠活动,VPS低至18元,价格算是比较便宜的了。趣米云vps优惠套餐:KVM虚拟架构,香港沙田机房,线路采用三网(电信,联通,移动)回程电信cn2、cn2 gia优质网络,延迟低,速度快。自行封...
部落曾经在去年分享过一次Boomer.host的信息,商家自述始于2018年,提供基于OpenVZ架构的VPS主机,配置不高价格较低。最近,主机商又在LET发了几款特价年付主机促销,最低每年仅4.95美元起,有独立IPv4+IPv6,开设在德克萨斯州休斯顿机房。下面列出几款VPS主机配置信息。CPU:1core内存:512MB硬盘:5G SSD流量:500GB/500Mbps架构:KVMIP/面板...