`

COM原理与应用----COM的实现

    博客分类:
  • COM
阅读更多

1、COM的实现与操作系统平台密切相关

因为COM最初源于Microsoft Windows平台,所以COM实现部分(即COM库)很多地方直接用到了Windows系统的一些特性,比如系统注册表、动态连接库等等,但实际上 COM是一个与平台无关的组件软件模型。Windows上使用的COM标准只是COM的一个具体实现。

2、COM的实现方法

进程内组件(DLL ,in-process component)。

进程外组件(EXE ,out –of-process component)。

3、DLL程序的创建方法

(1)创建一个DLL工程

(2)创建DLL时,应该使用_stdcall调用习惯引出函数,并使用extern “C”说明符。这样能够保证与其他编译器和编程语言的兼容。

(3)按照传统的编程方法,编写一个DEF文件,用来描述DLL程序的模块信息,即列出所有引出函数,并给每个引出函数分配一个唯一的序号。在Win32平台上,可以不使用DEF文件,而直接在函数说明时使用_declspec(dllexport)说明符,如下:

extern “C” _declspec(dllexport) int _stdcall MyFunction();

4、客户程序操作DLL程序的三个系统函数

    LoadLibrary,装载DLL模块函数

    GetProcAddess,取引出函数地址的函数

    FreeLibrary,释放DLL程序的函数

5、DLL的三点说明

    (1)对于进程内组件,因为客户程序与DLL程序在同一个地址空间,所以,DLL程序不仅可以引出函数,也可以引出全局变量。

    (2)VC++提供了使用工具DumpBin,通过/EXPORTS选项可以列出DLL程序中的所有被引出的信息。(实际运行中需要LINK.EXE和MSPDB60.DLL的支持)

    (3)如果客户程序本身也是一个DLL程序,,则它一定要先被装入到进程空间中。

6、进程外组件与客户通信跨跃进程边界协同工作

(1)两个问题

    一个进程如何调用另一个进程中的函数。

    参数如何从一个进程被传递到另一个进程中。

(2)Windows平台上不同进程间通信的方法

    动态数据交换(DDE)

    命名管道(named pipe)

    共享内存

(3)COM采用的进程间通信的方法

    本地过程调用(LPC,local procedure call),用在同一机器的不同进程间的通信。

远过程调用(RPC),用于不同机器间的进程间通信。

跨进程通信是操作系统实现的重要部分,而且,在系统底层实现跨进程操作更为便利,因为在系统一级,它可以控制应用进程的资源分配,包括逻辑内存空间到物理内存的映射、CPU时间的调度等。从控制能力来讲,操作系统可以调用任何一个进程中的函数。

(4)应用程序调用其他进程中系统服务的过程

    上图的调用过程中涉及到跨进程操作,实际上也就是用到LPC。应用A实际上调用的是系统模块DLL,其称为存根(stub)模块。

(5)客户程序和进程外组件之间的调用关系

进程外组件较进程内组件的效率要低,但在跨进程的调用中也为客户程序带来了安全性。在代理DLL和存根DLL之间的通信是通过列集和散集(对参数和返回值进行翻译和传递)操作来完成的。

如果只考虑客户程序和组件程序,那么事情就简化的多了,客户程序调用接口成员函数就好像是直接进行的,如上图虚线所示。按照这样简化的结构,进程外组件和进程内组件就有了一致的模型了,COM正是通过这种方式实现进程模型的透明特性的。如果组件程序运行在不同的机器上,则代理DLL和存根DLL就通过RPC方式进行网络上的过程调用,从而实现分布式组件对象模型,所有这些特性的实现可以完全建立在操作系统提供的LPC和RPC模块基础上,而不需要应用系统开发人员去考虑这些底层的细节技术问题。

(6)进程外组件的实现

除了实现组件程序外,还应给实现代理DLL和存根DLL两个程序模块,它们只与 COM接口有关,只负责接口成员函数调用过程中的中间处理工作。如果使用自定义的COM接口,则应该建立自己的DLL程序;如果使用COM预定义的标准接口或者OLE接口,则可以直接使用系统提供的DLL,COM库会为我们处理这些细节。

7、通过注册表管理COM对象

    通常,组件对象的创建工作由COM来完成,COM库通过系统注册表(systrm registry)所提供的信息进行组件的创建工作。

 

8、COM组件注册信息

    注册表结构与COM库是直接相关的,实现COM库时必须同时定义出注册表的结构。在Windows平台上,COM库所要求的注册信息都被放到其注册表中。RegEdit.exe可以用来编辑注册表。

    COM组件信息在HKEY_CLASSES_ROOT的CLSID下。若是进程内组件,则组件的CLSID子键下包含了InprocServer32子键;若是进程外组件,则组件的CLSID子键下包含了LocalServer32子键,它们的缺省值为组件程序的全路径文件名。与CLSID同一层上,Interface子键给出了当前系统中一些COM接口的配置信息,TypeLib子键给出了当前系统中类型库的信息。代理DLL和存根DLL的信息分别保存在CLSID下的ProxyStubClsid或ProxyStubClsid32子键下。CLSID下的ProgID(program identifier ,程序标识符)子键记录了组件对象的类标识符,COM提供了两个API函数CLSIDFromProgID和ProgIDFromCLSID,用于在 128位正数值和类标识符之间转换。

    COM提供了在注册表中对COM组件进行分类的机制,分类的原理很简单,如果COM组件支持同样的一组接口,则可以把它们分到统一类中,一个组件对象可以被分到多个类中。

    类别信息也用一个GUID来描述,称为CATID。类别特性只是COM对象的部分特性,如果COM对象要加入到某个类别中,则它必须实现该类别指定的多有接口。在HKEY_CLASSES_ROOT键下有一个子键“Component Gategories”,包含了当前机器上所有的组件类别,其中列出了每个组件类别的CATID。用VC++提供的OleView.exe工具可以看到类别信息。

9、COM组件的注册操作

    当组件程序被安装到机器上之后,必须通过注册才能使客户程序通过注册表使用它。进程内组件不能直接运行,所以必须通过其他进程调用才能获得控制,而进程外组件可以直接运行,可以在执行过程中完成自身的注册操作。Windows系统工具RegSer32.exe,可用于注册进程内组件,大需要进程内组件提供相应的入口函数DllRegisterServer和DllUnregisterServer。

10、客户程序如何使用组件程序

    客户程序并不像第二章中那样直接调用组件程序的引出函数CreateObject,而是调用COM库的函数进行组件对象的创建工作,COM库的创建函数根据注册表的信息并调用组件程序的入口函数来创建组件对象。组件程序需要提供一个标准的入口函数DllGetObjectClass,用于提供本组件程序的组件信息。

11、类厂

    类厂可称为“对象厂”,因为类厂是COM对象的生产基地,COM库通过类厂创建COM对象。对应每一个COM类,有一个类厂专门用于该COM类的对象创建操作。类厂本身也是一个COM对象,它支持一个特殊的接口:IClassFactory。

接口IClassFactory的成员函数CreateInstance用于创建对应的COM对象,LockServer用于控制组件的生存周期。

12、类厂的使用

    因为类厂本身也是一个COM对象,用于其他COM对象的创建过程。它由引出函数DllGetObjectClass创建,DllGetObjectClass函数并不是COM库函数,而是由组件程序实现的引出函数。

    COM库在接到对象创建的指令后,它要调用进程内组件的DllGetObjectClass函数,由该函数创建类厂对象,并返回类厂对象的接口指针,COM库或者客户一旦有了类厂的接口指针,它们就可以通过类厂接口IClassFactory的成员函数CreateInstance创建相应的 COM对象。

13、COM库与类厂的交互

    在COM库中,有三个API函数可用于对象的创建,它们分别是CoGetClassObject、CoCreateInstance和 CoCreateInstanceEx。通常情况下,客户程序调用其中之一完成对象的创建,并返回对象的初始化接口指针。COM库与类厂也通过这三个函数进行交互。

    COM对象是进程内组件对象:CoGetClassObject调用DLL模块的DllGetClassObject引出函数,把参数clsid、iid 和ppv传给DllGetClassObject函数,由DllGetClassObject创建类厂,并返回类厂对象接口指针。

    COM对象是进程外组件对象:情形复杂得多。首先CoGetClassObject函数启动组件进程,然后一直等待,直到组件进程把它支持的COM类对象的类厂注册到COM中,于是,CoGetClassObject函数把COM中相应的类厂信息返回。因此,组件外进程被COM库启动时(带命令行参数 “/Embedding”),它必须把所支持的COM类的类厂对象通过CoRegisterClassObject函数注册到COM中,以便COM库创建 COM对象使用。当进程退出时,必须调用CoRevokeClassObject函数以便通知COM它所注册的类厂对象不再有效。组件程序调用 CoRegisterClassObject函数和CoRevokeClassObject函数必须配对,以保证COM信息的一致性。

    关于三个创建对象的函数的选择:

(1)              如果创建远程对象或者希望一次获得对象的多个接口指针,则选用CoCreateInstanceEx函数。

(2)              如果希望获取类厂对象或者要调用类厂的某些成员函数,则选用CoGetClassObject函数,以便获得类厂对象,并对类厂对象进行操作。

(3)              在其他情况下,使用CoCreateInstance函数创建对象,这是最常用的方法。

 

14、CoGetClassObject与组件程序的交互过程的例子

用以说明在COM对象创建过程中,客户程序、COM库和进程内组件程序三者之间的顺序关系。

15、类厂对组件生存期的控制

    类厂是一个COM对象,但通常只把它当作创建其他组件对象的手段,一般情况下,客户程序或者COM库只是在创建组件对象的时候才使用类厂对象的接口指针,创建完成后就把类厂对象丢弃掉。如果用户希望保留类厂的接口指针继续使用,则在类厂中引入锁计数来控制组件程序的生存周期。

16、COM库

    COM库在整个COM对象体系中起了很重要的作用。COM除了定义了组件程序和客户程序交互的规范以外,它也提供了COM的实现部分即COM库,使得这些规范能够被真正地应用起来。并且,COM库也充当了组件程序和客户程序之间的桥梁,尤其是在组件对象的创建过程中,以及在对象管理、内存管理和一些标准化操作等方面起着重要的作用。

    在客户程序和组件程序建立起协作关系之前,它们之间的通信只能靠COM库来传递,并且组件程序和客户程序都可能要用到COM库提供的各种服务。

17、COM库的初始化与卸载

    COM库的初始化函数是CoInitialize,其参数pMalloc用于指定一个内存分配器,它是一个IMalloc指针接口,可由应用程序指定内存分配原则。一般将pMalloc设为NULL,由COM库将使用缺省提供的内存分配器。

    一个进程对COM库只需要(也必须)进行一次初始化。在成功初始化并使用完COM库后,必须调用COM库的终止函数CoUninitialize。但有一个函数的调用不需要COM库的初始化与卸载,就是CoBuildVersion,该函数用于获取COM库版本。

 

18、COM库的内存管理

    (1)内存使用的两种情况:一种是在客户程序和组件程序建立协作关系之前,靠COM库进行通信,COM需要申请内存,内存不一定是COM库本身使用,


(2)COM库不仅提供了这样的内存管理器,还提供了内存管理器的标准,应用程序可以按照COM规范指定的标准建立自定义内存管理器,以取代COM库的缺省内存管理器。

    (3)在COM库初始化成功之后,不管是使用缺省内存管理器还是使用自定义的内存管理器,应用程序都可以使用COM库进行内存分配或释放,为此,COM库提供了两种操作方法:

           A、直接使用IMalloc接口指针。在客户程序或者组件程序中调用COM库函数CoGetMalloc,通过IMalloc接口指针和CoGetMalloc函数实现内存管理的统一。

           B、COM库封装了三个API函数,可用于内存分配和释放:CoTaskMemAlloc、CoTaskMemRealloc、 CoTaskMemFree。这三个函数分别对应于IMalloc的三个成员函数:Alloc、Realloc和Free,参数的定义也完全一致。

    (4)COM库的两种内存管理器:CoGetMalloc函数可用来获取COM库的内存管理器。一种是在初始化时指定的内存管理器或者其内部缺省的管理器(即作业管理器,task allocator),这种管理器在本进程内有效;另一种是跨进程的共享分配器,由OLE系统提供,它可在一个进程内分配内存并传给第二个进程,在第二个进程内使用此内存甚至释放掉此内存。

19、组件程序的装载和卸载

    COM库对组件程序的装载和卸载进行控制。客户程序是在运行时刻与组件程序建立连接的,而且,一旦连接起来以后,客户程序和组件程序的通信是直接进行的,并不需要COM库的参与,但组件程序的装载是在客户创建第一个组件对象时进行的,组件程序的卸载是在最后一个组件对象被释放之后进行的,这两个动作并不由客户程序直接完成,而是在COM库中完成的。

    进程内组件的卸载满足的两个条件:组件中对象数为0,类厂的锁计数器为0。客户程序调用CoFreeUnusedLibraries函数完成卸载工作。

    进程外组件的卸载比较简单,因为组件程序运行在单独的进程中,一旦退出的条件满足,它只要从进程额主控函数返回即可。在Windows系统中,进程的主控函数为WinMain。类厂对象的引用计数无法控制进程的生存期,所以引入类厂对象的加锁和减锁操作。

20、COM库的常用函数


在COM库中还给出了许多标准接口的定义,例如IUnknown、IClassFactory、IMalloc。

21、HRESULT类型

    在COM中大多数的函数以及一些接口成员函数的返回值类型均为HRESULT类型。HRESULT类型的返回值反映了函数调用过程中的一些情况,而且HRESULT类型定义也有一定的规范。

    HRESULT并不是指向结果结构的句柄,而是一个32位整数,通常被定义为DWORD或long类型。HRESULT的32位被分成四个域:类别码(30-31)、自定义标志位(29)、操作码(16-28)、操作结果码(0-15)。

Win32 SDK的头文件WinError.h定义了Win32函数所有的可能返回结果,其中也包括了COM库函数以及OLE函数的返回值的宏定义。Win32 SDK提供的FormatMessage函数可根据结果值获得一个对应于该结果值的标准说明字符串,它也支持COM库函数的返回结果信息。

一般推荐在使用HRESULT类型作为引出函数或者作为接口成员函数的返回值时,尽量使用COM或者Win32提供的标准定义。

22、COM的实现是COM客户程序、COM库和COM组件程序三者之间通过COM制定的规范协同工作来完成的,三者之间形成了一个统一的整体。

23、第二章的字典组件程序是一个模拟组件程序,第三章的字典组件程序是真正的COM组件程序,这样,在运行客户程序之前必须先注册组件程序,命令行为:regsvr32.exe …\DictComp.dll 。

分享到:
评论

相关推荐

    嵌入式实时操作系统μCOS-II原理及应用-任哲(高清版本)

    《嵌入式实时操作系统μCOS-II原理及应用》是由任哲编著的一本深入解析UCOS-II操作系统的专著。这本书主要针对嵌入式开发人员,详细阐述了μCOS-II实时操作系统的核心机制和实际应用,是学习和掌握该操作系统的重要...

    传感器原理与应用-电感式传感器

    ### 传感器原理与应用——电感式传感器 #### 一、概述 电感式传感器是一种广泛应用的检测设备,它能够将物理量的变化转化为电信号输出。这类传感器利用电磁感应原理来工作,根据不同的应用场景和需求,电感式...

    ARM Cortex-M0原理与应用实践V1.5.pdf

    ### ARM Cortex-M0原理与应用实践 #### 一、ARM Cortex-M0简介 **ARM Cortex-M0** 是ARM公司推出的一款低功耗、高性能的32位微控制器内核。这款内核专为嵌入式应用设计,尤其适用于那些需要低功耗、小面积和低成本...

    数据库原理与应用-东南大学-徐立臻教授.zip

    数据库原理与应用是计算机科学中的一个核心领域,它涉及到数据的组织、存储、检索和管理。这门课程由东南大学的徐立臻教授讲授,旨在深入探讨数据库系统的概念、设计与实现。在这个名为"DatabaseStudy-master"的...

    直线电机原理与应-叶云岳

    ### 直线电机原理与应用 #### 一、直线电机概述 直线电机是一种将电能直接转换为直线运动的电机,无需通过中间机械结构(如齿轮或丝杠)即可实现直线运动,这使得其在很多应用场景下具有独特的优势。根据工作原理...

    嵌入式实时操作系统μCOS-II原理及应用-任哲(高清版本).zip

    《嵌入式实时操作系统μCOS-II原理及应用》是由任哲编著的一本深入解析μCOS-II操作系统的书籍,旨在帮助读者理解和掌握实时操作系统的基本概念和μCOS-II的具体实现。μCOS-II是一种广泛应用的小型、高效、可移植的...

    教材:《卡尔曼滤波原理及应用-MATLAB仿真》 黄小平 王岩 编著 卡尔曼原理及应用-MATLAB仿真-滤波源码

    卡尔曼滤波的原理是基于贝叶斯定理,它将系统的状态看作是一个随机变量,通过对系统的测量值和模型进行处理,得到系统状态的后验概率分布,从而实现对系统状态的估计。 在实际应用中,卡尔曼滤波广泛应用于航空、导航、...

    MIMO-OFDM系统原理、应用及仿真

    **MIMO-OFDM系统原理、应用及仿真实现** 多输入多输出正交频分复用(Multiple-Input Multiple-Output Orthogonal Frequency Division Multiplexing, MIMO-OFDM)是现代无线通信系统中的一种关键技术,广泛应用于4G...

    地理信息系统原理方法和应用-邬伦

    综上所述,《地理信息系统原理方法和应用》一书系统地介绍了GIS的基本概念、理论基础、功能实现和技术应用,对于GIS领域的初学者、研究人员和应用人员都具有很高的参考价值。该书不仅涵盖了GIS的核心理论,还关注了...

    任哲-μCOS-II原理及应用-课本及其笔记

    但是,我可以根据提供的标题、描述和标签,对μCOS-II原理及其应用进行一般性介绍。 μCOS-II(MicroC/OS-II)是由Jean J. Labrosse编写的一个实时操作系统(RTOS),它被广泛应用于嵌入式系统中。μCOS-II具有公开...

    《MIMO-OFDM系统原理、应用及仿真》李莉全部代码

    《MIMO-OFDM系统原理、应用及仿真》李莉全部代码 本书系统地阐述了下一代宽带移动通信两大核心技术(OFDM、MIMO)及两者联合技术(MIIMO-OFDM)的基本原理与关键技术。本书从无线信道与MIMO信道模型及MIMO、MIMO-...

    大数据技术原理与应用(实验二)

    ### 大数据技术原理与应用(实验二) #### 实验背景及目标 本次实验报告针对的是《大数据平台核心技术》课程中的一个实践性学习任务。实验的主要目的是帮助学生掌握Hadoop分布式文件系统(HDFS)的基本操作,理解...

    论文研究-自然人造复合系统的开发原理与途径------以区域大中型沼气能源工程系统开发为例.pdf

    针对系统开发问题,提出了通过各子系统人员责任和目标的实现,实现系统总目标的自然人造复合系统开发原理,新建了系统仿真与``干中学''结合的自然人造复合系统开发途径.以井冈山西部萍乡市泰华养殖场区域大中型沼气...

    《嵌入式系统原理与实践--ARM Cortex-M4 Kinetis微控制器》网上光盘

    《嵌入式系统原理与实践--ARM Cortex-M4 Kinetis微控制器》是一本深入探讨嵌入式系统设计和实践的书籍,主要聚焦在ARM Cortex-M4处理器和Kinetis微控制器系列上。ARM Cortex-M4是ARM公司推出的一款高性能、低功耗的...

    单片机原理及应用-第2章__MCS-51单片机的结构和工作原理.ppt

    【单片机原理及应用-第2章__MCS-51单片机的结构和工作原理】 在深入探讨MCS-51单片机的结构和工作原理之前,我们首先要明白单片机的基本概念。单片机是一种集成电路,集成了计算机的核心组件,包括CPU、内存、输入/...

    dsp原理与应用实验指导.pdf

    ### DSP原理与应用实验指导知识点总结 #### 一、CCS基本操作 - **知识点概述**: - CCS(Code Composer Studio)是一款由TI(德州仪器)提供的集成开发环境,主要用于DSP(数字信号处理器)的软件开发。 - **安装...

    S7-300现代可编程序控制器原理与应用

    《S7-300现代可编程序控制器原理与应用》是关于西门子S7-300系列PLC(可编程逻辑控制器)的一份深入学习资料,它涵盖了该控制器的基本概念、工作原理以及实际应用。S7-300作为西门子中型PLC系统,广泛应用于工业自动...

    DSP原理与应用.pdf

    ### DSP原理与应用知识点概述 #### 一、CCS软件应用实验 **1.1 CodeComposer Studio入门** - **知识点1:CCS简介** - CCS(Code Composer Studio)是一款集成开发环境(IDE),专为德州仪器(TI)的数字信号处理器(DSP...

Global site tag (gtag.js) - Google Analytics