1、COM对象的理解

COM对象类似于C++语言中类的概念,类的每个实例代表一个COM对象,它也包括属性(即状态)和方法(即操作),状态反映对象的存在,方法就是接口。

2、COM对象的标识-CLSID

GUID是一个128位的随机数,重复概率极低。它的值来源于两部分:空间值(网卡地址或随机数)和时间值。

获得GUID值可以使用VC++提供的工具:GUIDGen.exe 和 UUIDGen.exe。或者使用COM库的API函数CoCreatGuid()。

3、COM对象与C++对象的比较

COM对象将数据完全封装在对象的内部。C++对象的封装是在语义上的封装,通过不同的数据类型实现数据的封装。

COM对象的可重用性通过包容和聚合实现。C++对象的可重用性通过类的继承来实现。

COM对象的多态性通过其接口体现,C++对象的多态性通过其虚函数体现。

4、COM接口的作用和意义

COM规范的核心内容是关于接口的定义,虽然COM本身并不复杂,但是围绕COM接口有很多内容值得仔细探讨,包括接口的标识、接口函数的调用习惯、参数处理、接口与对象的关系以及接口与C/C++的关系、COM接口多具有的特性等。

COM定义了一套完整的接口规范,不仅可以弥补API作为组件接口的不足,还从分发挥了组件对象的优势,并实现了组件对象的多态性。

5、接口定义和标识

从技术上讲,接口是包含了一组函数的数据结构,通过这组数据结构,客户代码可以调用组件对象的功能。

客户程序用一个指向接口函数结构的指针来调用接口成员函数。实际上接口指针指向另一个指针pVtable。

接口函数表称为虚函数表(Virtual Function Table ,简称vtable),指向vtable的指针为pVtable。对于一个接口来说,它的虚函数表vtable是确定的。

6、接口设计的问题

在接口成员函数中,字符串变量必须用Unicode字符指针,这是COM规范的要求。

COM API函数使用大多数语言惯用的_stdcall调用习惯。

用C语言定义COM接口,需要有结构体struct定义其接口结构,接口成员函数必须有一个this指针。

用C++语言定义COM接口,因为由C++语言class的实现机理可以看出,COM接口结构中的vtable与class的vtable(类的虚函数表)完全一致,因此,用class描述COM接口是最方便的手段。此时,接口成员函数隐藏了this指针。

class 型接口的说明要比struct 型接口的说明简捷得多。

7、COM接口与对象的联系

接口类只是一种描述,并不提供具体的实现过程。如果COM对象要实现接口,则COM对象必须以某种方式把它自身与接口类联系起来,然后把接口类的指针暴露给客户程序,于是客户程序就可以调用对象的接口功能了。

用 class型接口通过把接口指针(this)与对象数据绑定在一起的方法实现对COM接口的支持比较直观、简捷易于理解。实际上,也可以采用其他的方法来实现接口,只要接口成员函数中this指针(即接口指针)与对象数据能建立确定的连接,在接口成员函数中可以访问到对象数据即可。例如,VC++的MFC 库和ATL(active template library ,活动模板库)模板库分别采用了不同的机制来提供对COM接口的支持。

8、接口描述语言IDL

COM 规范在采用OSF的DCE规范描述远程调用接口IDL(interface description language ,接口描述语言)的基础上,进行扩展形成了COM接口的描述语言。接口描述语言提供了一种不依赖于任何语言的接口描述方法,因此,它可以成为组件程序和客户程序之间的共同语言。

COM 规范使用的IDL接口描述语言不仅可用于定义COM接口,同时还定义了一些常用的数据类型,也可以描述自定义的数据结构,对于接口成员函数,我们可以制定每个参数的类型、输入输出特性,甚至支持可变长度的数组的描述。VC++提供了MIDL工具,可以把IDL接口描述文件编译成C/C++兼容的接口描述头文件(.h)。

9、接口的内存模型

COM对象往往有自己的属性数据,它们反映对象的状态,并用于区分不同的对象。对于有多个对象的客户,数据属性是不能公用的。

10、接口的特点

二进制特性

接口不变性

继承性(扩展性):类似于C++中类的继承性,接口也可以继承发展,但方式不同。类继承不仅是说明继承,也是实现继承,即派生类可以继承基类的函数实现,而接口继承只是说明继承,即派生的接口只继承了基接口的成员函数说明,而没有继承基接口的实现。类继承允许多重继承,但接口继承只允许单继承。根据COM规范,所有接口都必须从IUnknown派生,可以直接派生,也可以间接派生。但大多数都是直接派生。OLE系统中,接口最后字母是“2”或“Ex”的,标煤它是一个继承接口。

多态性:COM对象具有多态性,其通过COM接口体现。

11、IUnknown接口提供了两个非常重要的特性:生存期控制(使用引用计数)和接口查询。

12、IUnknown接口引用计数的设置层级

引用计数在组件一级实现则计数分辨率太粗(选择全局变量),在对象一级实现恰好(使用C++类的成员变量),在接口一级实现则计数分辨率太细(使用类成员变量)。

13、使用引用计数的规则

根据不同场合使用或者传递接口指针标量进行分类,并给出相应的规则:

(1)函数的参数中使用接口指针变量。

输入参数:由于输入参数由调用函数控制,因此被调用函数执行过程中,接口指针一定保持有效,引用计数不需要改变。

输出参数:输出参数是指在被调用函数执行过程中进行赋值的参数,而且被调用函数并没有用到函数初始化传进来的值,输出参数相当于函数的一个返回值。在C/C++语言中,输出参数为一个指针变量(COM中不使用引用变量)。因为输出参数相当于在被调用函数中生成了一个新的接口指针变量,因此,在被调用函数返回之前,对输出参数应该调用AddRef使接口引用计数增1。这条规则也适用于函数返回值为接口指针变量的情况。

输入-输出参数:在参数被修改之前,对原来传进来的接口指针调用Release以使引用计数减1,在参数被修改之后,对新的接口指针变量调用AddRef,以标记对新的接口指针的引用。如果在函数执行过程中参数没有被修改,则不需要改变。

(2)局部接口指针变量:因为在局部函数块中,接口指针总是有效的,所以,一个局部接口指针变量被赋了值并调用了接口成员函数,引用计数不需要改变。

(3)全局接口指针变量:把全局接口指针变量作为输入参数传给某个函数之前,应该调用AddRef以保证在函数调用中可以使用给接口指针变量,因为它是全局变量,其他的函数有可能会调用Release函数。在函数返回之后应该调用Release函数。

(4)C++中类成员变量为接口指针变量:因为对于类的作用域来讲,成员变量相当于全局变量,因此适用于规则(3)。

(5)当以上情形都不适合时,使用以下一般的规则:

在顺序执行过程中,如果要对一个接口指针变量赋值,则对赋值后的接口指针变量调用AddRef,并且,如果赋值前的接口指针变量还没有结束,则赋值前必须对它调用Release以便先结束它的使用。

如果要结束使用一个接口指针变量,以后不再用到它了,则调用Release函数。

14、接口查询

使用QueryInterface函数查询接口,其返回值有S_OK、E_NOINTERFACE、E_UNEXPECTED。

15、COM对象的接口原则

(1)对于同一个对象的不同接口指针,查询得到的IUnknown接口必须完全相同。即每个对象的IUnknown接口指针是唯一的。

(2)接口对称性。即对一个接口查询其自身总应该成功。

(3)接口自反性。

(4)接口传递性。

(5)接口查询时间无关性。

16、多接口COM对象的实现方法

在C++语言中有两种实现方法:一是使用多重继承,把所支持的接口作为其基类,然后在对象类中实现接口成员函数;二是使用内嵌接口类成员。

Com原理及應用——Com對象和接口的更多相关文章

  1. 【夯实Nginx基础】Nginx工作原理和优化、漏洞

    本文地址 原文地址 本文提纲: 1.  Nginx的模块与工作原理    2.  Nginx的进程模型    3 . NginxFastCGI运行原理        3.1 什么是 FastCGI   ...

  2. 玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

    Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services.exe -unregserver Windows服务Release版本 注册 Servi ...

  3. EasyMock 使用方法与原理剖析

    from:http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/ Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一 ...

  4. EasyMock 使用方法与原理剖析--转载

    原文地址:http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/ Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一 ...

  5. 【转】Android LCD(二):LCD常用接口原理篇

    关键词:android LCD TFT TTL(RGB)  LVDS  EDP MIPI  TTL-LVDS  TTL-EDP 平台信息:内核:linux2.6/linux3.0系统:android/ ...

  6. 玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

    原文:玩转Windows服务系列——Debug.Release版本的注册和卸载,及其原理 Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services ...

  7. 开源纯C#工控网关+组态软件(四)上下位机通讯原理

    一.   网关的功能:承上启下 最近有点忙,更新慢了.感谢园友们给予的支持,现在github上已经有.目标是最好的开源组态,看来又近一步^^ 之前有提到网关是物联网的关键环节,它的作用就是承上启下. ...

  8. Netty中ByteBuf的引用计数线程安全的实现原理

    原文链接 Netty中ByteBuf的引用计数线程安全的实现原理 代码仓库地址 ByteBuf 实现了ReferenceCounted 接口,实现了引用计数接口,该接口的retain(int) 方法为 ...

  9. Spring Boot的Listener机制的用法和实现原理详解

    之前在介绍了在spring-boot启动过程中调用runner的原理,今天我们介绍另外一种可以实现相似功能的机制:spring-boot的Listener机制. 通过注册Listener,可以实现对于 ...

随机推荐

  1. drop table xx purge

    drop table xx purge; 说明: 所有删除的表都会在回收站里面,只有后面加上purge才是彻底的清空表. (一般用于测试.练习数据表,所以最好不要带purge,要不误删就找不到了.)

  2. C#串口控制

    串行口是计算机的标准接口,现在的PC机(个人电脑)一般至少有两个串行口COM1和COM2.串行口应用广泛,在数据通信.计算机网络以及分布式工业控制系统中,经常采用串行通信来交换数据和信息.本节通过几个 ...

  3. IIS7、IIS6 web.config注册HttpModule

    IIS6注册HttpModule <system.web>     <httpModules>       <add name="..." type= ...

  4. hibernate_validator_07

    一.校验组序列 默认情况下,约束的验证是没有一定的顺序的,不管他们是属于哪个认证组的.但是在有些环境中,我们控制这些约束验证的顺序还是很有用的. 就拿我们上一个例子来说,我们可以这样:首先在我们检查车 ...

  5. hdu1690 Bus System(最短路 Dijkstra)

    Problem Description Because of the huge population of China, public transportation is very important ...

  6. ONVIF Event消息解析(How to work with gSoap)

    Prepare Requirements ONVIF Event gSoap reference ONVIF Specification 问题描述 Event是ONVIF核心规范中一块, 文档解释了如 ...

  7. TCP/IP-IP

    A contented mind is a perpetual feast. "知足长乐" 参考资料:TCP/IP入门经典 (第五版) TCP/IP详解 卷一:协议 一.简介 IP ...

  8. Linux 0.11下信号量的实现和应用

    Linux 011下信号量的实现和应用 生产者-消费者问题 实现信号量 信号量的代码实现 关于sem_wait和sem_post sem_wait和sem_post函数的代码实现 信号量的完整代码 实 ...

  9. 第三方分页控件aspnetPager出现问题解决方法

    问题描述: 今天在打开以前的项目使用vs2013打开后并且生成解决方案的时候发现报错了.经过检查发现是由于第三方分页控件aspnetPager在页面上不能引用到了. 解决方法: 1. 首先将AspNe ...

  10. iOS页面间传值的方式 (Delegate/NSNotification/Block/NSUserDefault/单例)

    iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)   iOS页面间传值的方式(NSUserDefault/Delegate/NSN ...