COM原理
+ -

COMM 接口简介

2022-02-16 41 0

知道了CLSID或ProgID唯一地表示一个组件服务程序,那么根据这些ID,就可加载运行组件,并为客户端程序提供服务。启动组件程序的方法,会陆续介绍。

接下来先讨论如何调用组件提供的函数?接口。

作为客户端程序员,希望或要求:写一个程序时,不做任何修改可调用任意一个组件。举例来说:

在Word中可嵌入Excel,也可嵌入Picture,或任何第3方发表的ActiveX文档。也就是说,连Word自己都不知道使用它的人将会在doc里面插入什么东东;可在HTML文件中插入一个ActiveX,也可插入一个程序脚本Script,自己写一个插件也可插入到IE环境中。为完成这个功能,绝对也不会去让微软修改IE吧!这个要求实在有点难度,Office开发停滞了。说来话巧,一天老O(Office项目总工程师)和小B(VB项目总工程师)一起喝酒,老O向小B倾诉了它的烦恼:

  • 老O:怎么能让我写的程序C,可调用其它人写的程序S中的函数?(C表示客户程序,S表示提供服务的程序)
  • 小B:你是不是喝糊涂了?把S作成DLL,你去LoadLibrary、GetProcAddress、…FreeLibrary!
  • 老O:废话!要这么简单就好了。问题是,连我都不知道这个S程序是干什么的?能干什么?我怎么调用呀?
  • 小B:VB中制定了一个标准,允许任一VB开发者,把它写的小程序放在VB工具栏上,这就好象它扩展了VB的功能。
  • 老O:这个VBX标准是什么?
  • 小B:特简单,就是在VBX中必须实现7个函数,功能是:初始化、释放、显示、消息处理……,而至于它内部干什么,我管不着。我只是在需要时调用这7个函数
  1. 程序C要能调用任何人写的程序B。那么B必须要按照事先要求,提供需要的函数F1(),F2(),F3(),K1(),K2()。
  2. BASIC是解释执行,因此它的函数不用考虑书写顺序,只要给出函数名,解释器就能找到。
  3. 编译后的C++代码中没有函数名,只有函数地址,因此必须改进为用VTAB(虚函数表)表示的函数入口
    C++ VTAB的结构如下:
    VTAB的结构

    C++多个VTAB的结构:
    多个VTAB的结构

  4. 还需要改进,因为所有函数地址放在一个表中不灵活、不易扩展。有了!按函数功能分类:
  5. 现在有2个VTAB表,怎么从一个表找到另一个表那?又有办法了,要求必须实现一个函数,且这个函数地址必须放在所有表的开头(表中的第一个函数指针),这个函数就叫QueryInterface,完成从一个表查找到另一个表的功能。
    除了QueryInterface函数,顺便也完成另外两个函数,叫AddRef和 Release。
    QueryInterface函数
  6. 为了以后描述方便,不再使用图四方法,而使用下图这样简洁的样式:
    COM接口结构简洁图示

接口(Interface)概念

函数通过VTAB虚函数表提供其地址。从另一个角度看,不管用什么语言开发,编译器产生的代码都能生成这个表。这样就实现了组件的“二进制特性”跨语言要求。假设有一个指针变量保存着VTAB的首址,这个变量就叫“接口指针”,变量命名时,习惯加上”I”开头。另外,为区分不同的接口,每个接口也都要有一个名字,该名字和CLSID一样,使用GUID方式,叫IID。

  • 接口一经发表,就不能再修改。不然就会出现向前兼容的问题。这个性质叫“接口不变性”。
  • 组件中必须有3个函数,QueryInterface、AddRef、Release,这3个函数也组成一个接口,叫”IUnknown”。
  • 任何接口,其实都包含了IUnknown接口。随着接触到更多接口就会体会到接口的另一个性质“继承性”。
  • 在任何接口上,调用表中的第一个函数QueryInterface,就会得到另一个接口指针。这个性质叫“接口的传递性”。
  • 在C/C++中,函数需要事先声明,这就要求组件提供C语言头文件。为使COM具有跨语言的能力,因此不再为任何语言提供对应函数接口声明,而是独立提供一个称为类库(TLB)的声明。
  • 每个语言IDE环境,根据TLB生成各自语言的包装。这个性质叫“接口声明的独立性”。

小结

这里介绍了两个非常重要的概念:CLSID和Interface。IDispatch接口IID是多少?
想知道为什么COM函数总返回 HRESULT吗?想知道如何使用BSTR、VARIANT吗?
想知道COM中该如何使用内存吗?想知道如何使用UNICODE吗?

  • 注1:GUID全局唯一标示符,CLSID/IID其实是借用了GUID的概念。
  • 注2:ProgID = Program ID,等价于CLSID,是用串表示的。
  • 注3:注册表子键ProgID和VersionIndependentProgID分别表示真正的ProgID和版本无关的ProgID。我的计算机安装了Excel,它的ProgID=”Excel.Application.9”,VersionIndependentProgID=”Excel.Application”。
  • 注4:Interface = 接口,以前微软不叫它接口叫协议Protocol。
  • 注5:IUnknown的IID=IID_IUnknown;注册表样式{00000000-0000-0000-C000-000000000046}。
  • 注6:TLB是由一个描述接口的文件IDL经过编译产生的。IDL说明见后续文章。
  • 注7:IPersistStorage是用复合文件的存贮(Storage)功能来保存/读取数据用的一个接口。
  • 注8:IPersistStreamInit 是用复合文件的流(Stream)功能来保存/读取数据用的一个接口。

0 篇笔记 写笔记

WDM驱动相同硬件相同驱动接口区分
在项目开发的时候,经常会做一些设备驱动,一块主板上安装上多块相同的板卡,(例如:同一PC机的主板上会插多块PCI 串口板卡。)这时在驱动开发的时候,在AddDevice回调函数中会以设备类的方式注册设备。DEFINE_GUID(PCI_DEVICE, 0x5f655dad, 0x16d4, 0x4......
SetupApi用户接口函数
可以在类安装程序和联合安装程序中使用以下设置函数来确定当前进程是否可以与用户交互。FunctionDescription SetupGetNonInteractiveModeReturns the value of a SetupAPI non-interactive flag......
SetupDi Device Interface 函数
SetupDiCreateDeviceInterfaceRegisters device functionality (a device interface) for a device.SetupDiOpenDeviceInterfaceRetrieves information......
Windows设备树及设备信息管理接口
Windows下的所有设备都会挂接在其设备树上,设备树由PNP管理器来维护。如一个设备树如下图所示:设备树上每个节点代表一个设备,凡是有子节点的节点是一个总线设备,其负责枚举下子节点设备,这样进行层层枚举,形成一棵设备树。其中根节点由PNP管理器创建,其用于挂载ACPI子节点。ACPI是一个抽象的......
PortClass 电源管理
电源管理实现的COM是AdapterPowerMgr,继承于IAdapterPowerManagement和CUnknown,用于电源的管理。class AdapterPowerMgr: public IAdapterPowerManagement, public CUnkn......
COM的QueryInterface与NonDelegatingQueryInterface关系
COM类的实现如下:class CMyComponent : public CUnknown, public ISomeInterface{public: DECLARE_IUNKNOWN; STDMETHODIMP NonDelegatingQueryInterface(RE......
COM的QueryInterface与NonDelegatingQueryInterface的测试用例
在COM中,函数的调用实际是汇编 call 函数地址.对于一个类里定义的函数实际是一个一个的地址偏移.如果地址偏移是一样而且参数个数与排列都一样,函数叫什么名字是没有关系的。这里关于这句话做一个测试用例,用于测试COMM的妙用:#include #include......
COM的应用
当给组件增加函数时,无需修改已发表的接口,而是提供一个新的接口来完成功能扩展。组件A有2个自定义接口,组件B是A的升级,接口结构如下:假设设计了组件A,它有2个自定义接口。IMathe有Add方法完成整数加法,IStr有Cat方法完成字符串连接。升级组件A到B,欲增加一个Mul方法完成整数乘法。由于......
COM 接口描述语言IDL
COM规范在IDL接口描述语言(OSF的DCE规范)的基础上,通过扩展形成了COM接口的描述语言。接口描述语言提供了一种不依赖于任何语言的接口的描述方法,因此,可成为组件程序和客户程序之间的共同语言。COM规范使用的IDL不仅可用于定义COM接口,同时还定义了一些常用数据类型,也可描述自定义的数据......
COM 可连接对象(源对象)
首先 两个概念:入接口 :源对象提供给客户调用的。出接口 :源对象通过此接口可直接或间接调用客户。类似delegate如果一个COM对象支持一个或多个出接口,这样的对象称为可连接对象。有时也称源对象。可连接对象的出接口也是COM接口,它包含一组成员函数,每个成员函数代表了一个事件、一个通知,......
COMM 接口简介
知道了CLSID或ProgID唯一地表示一个组件服务程序,那么根据这些ID,就可加载运行组件,并为客户端程序提供服务。启动组件程序的方法,会陆续介绍。接下来先讨论如何调用组件提供的函数?接口。作为客户端程序员,希望或要求:写一个程序时,不做任何修改可调用任意一个组件。举例来说:在Word中可嵌......
APO音频处理象开发概述及对接口关系
自定义音频处理对象APO的步骤:创建自定义 APO com 对象以提供所需的音频处理对象。创建用户界面以使用配置自定义 APO(可选)。创建 INF 文件以安装和注册 APO 和自定义用户界面。APO 必须有一个输入和一个输出连接。这些连接是音频缓冲区,可以有多个通道。APO 只能修改通过其I......
SwapAPO COM接口关系图
总目录为SwapAPODlllib,其UUIP定义为:// SwapAPODlllib//[ uuid(7092F0B2-D28D-4095-95A7-6C37A97432A2), version(1.0)]其包含2个COM类,分别为SFX和MFXlibrary Swap......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!