组件化编程及数据变化通知机制

2011-09-26 02:03徐丽群
上海电力大学学报 2011年6期
关键词:调用组件对象

刘 刚,徐丽群

(上海电力学院电力与自动化工程学院,上海 200090)

随着计算机技术和软件科学的不断发展,新的应用系统越来越复杂,用户对应用软件也有了更高的要求,既要保证软件在升级应用时不破坏其功能,又要保证升级后该软件能与以前的版本相互兼容,传统的面向对象的思想已经难以适应这种分布式软件模型.因此,基于组件的程序设计方法越来越受到重视.组件化程序设计思想是将复杂的应用设计成小的、功能单一的组件模块,不依赖特定的操作系统就可以扩展系统服务.一个新的软件,就好像搭积木一样,可以将不同的组件结合在一起组成一个新的应用软件[1].

组件化程序设计方法在实施过程中必须遵守一定的标准,组建对象模型 (Component Object Module,COM)则为组件程序之间提供了规范.引入COM的组件化程序设计只要遵守COM标准,就可以选择适合的编程语言进行编程,不用担心因语言不同而出现调用和管理差错,而且还可以通过增加新接口来提供新服务.利用COM提供的包容和聚合,可以很好地使组件得到扩展[2].

本文对计算机COM技术的基础和原理进行了分析,深入研究COM标准的底层实现细节和数据通报机制,并通过在Visual C++中调用MATLAB绘制随机曲线和在基于COM技术的力控组态软件模拟了火电厂锅炉汽包水位数据变化通知机制的应用,以深入了解COM技术.

1 COM技术介绍

COM为Windows提供了一个统一的、可扩充的、面向对象的通信机制.开发COM的目的是为了使软件更易于定制、扩充更灵活.它可以将原来一个整体的应用程序拆分成几个组件(components),从而实现像搭“积木”一样,将组件“搭建”起来完成新的应用程序的开发.

1.1 COM对象与接口

COM对象,就是在程序与程序之间进行通信的双方.对于客户来说,COM对象本身是不可见的,只能通过接口来获得对象服务.接口是对象或者组件的通信协议,实现对象或者组件的内部细节[1].

一个组件程序可以包含多个COM对象,一个COM对象也可实现多个接口.一个COM组件可以是一个动态连接库(Dynamic Linking Library,DLL)文件,也可以是一个EXE文件.COM组件和COM对象与COM接口之间的关系如图1所示.

图1 COM组件和COM对象与COM接口之间的关系

对于客户来说,对象本身是不可见的,而且客户也无需知道对象内部的实现细节,客户通过对象提供给外界的COM接口就可以获得对象的服务,因此接口对于组件与组件之间的交互显得十分重要.COM接口是一组逻辑上相关的函数集合,每个接口由一个128位的全球唯一标识符(Globally Unique Identifier,GUID)来标识.与接口类似,COM对象也有一个128位的全球唯一标识符,称为类标识符(Class Identifer,CLSID)[2].所有的COM接口都必须从IUnknown继承过来,IUnknown包含3个成员函数:QueryInterface(),AddRef(),Release(),其中 QueryInterface()为接口查询函数.AddRef()和Release()实现的是一种名为引用计数的内存管理技术.通过它们,组件可以很好地进行自我删除[3].

1.2 COM特性

COM具备面向对象的继承、封装、多态等性能,并在此基础上发展了一些其他特性.

(1)语言无关性 COM对象是建立在二进制可执行代码级的基础上,这一特性使得用不同编程语言开发的组件对象之间进行交互成为可能.

(2)进程透明性 COM所提供的服务组件对象在实现时有进程内对象和进程外对象两种进程模型.但客户程序在使用组件对象时可以无视这种区别的存在,只要遵照COM规范就可以了.

(3)可重用性 客户程序可通过接口使用COM对象的服务,但并不知道其内部是如何实现的,因此这种重用是建立在行为方式而不是具体实现上,这是COM重用的关键所在.COM提供了包容(containment)和聚合(aggregation)两种机制来实现对象的重用[4].

1.3 COM的实现

COM本身除了规范之外,也有实现部分,其中包括一些核心的系统级代码,也正是这部分核心代码,才使得对象和客户之间可以通过接口在二进制代码级进行交互.在编写COM应用时,可以直接利用COM库提供的API进行编程,而不是编写大量基础代码,从而加快了开发速度.类厂是COM对象的生产基地,COM库通过类厂创建COM对象,对应每一个COM类,有一个类厂专门用于该COM类的对象创建操作.

2 统一数据传输机制

COM在功能实现之间提供了一种有效的数据交换机制,称为统一数据传输机制(Uniform Data Transfer,UDT).它以数据对象作为数据实体,而数据对象则通过IDataObject接口暴露其内部信息.客户程序只要通过某种传输协议就可以得到数据对象的IDataObject接口,以后客户程序就可以直接访问数据对象了.

COM提供了连接点机制以实现双向通讯.在UDT中,客户程序只需实现IAdviseSink接口,其中OnDataChange成员用于数据对象的通知过程.IDataObject::DAdvise函数建立了客户程序接收器,在对象与数据对象之间通报连接,一旦连接建立起来,数据发生变化时,就会调用IAdviseSink::OnDataChange函数.

3 COM技术的应用分析

3.1 COM与MATLAB混合编程

Matlab支持组件自动化(COM Automation),即一个COM协议,该协议允许一个程序或组件去控制另一个程序或组件.

通过分析如何在Visual C++中调用Matlab COM Builder生成的组件,用于实现在Matlab中绘制随机曲线.在这里,Matlab生成的文件即为组件程序,而C++程序则为客户程序.

图2所示的myrandplottest对象有5个接口,其中的IUnknown接口是所有COM对象都支持的接口.接口Imyrandplottest则是自定义的接口,用于实现Matlab的图形绘制功能.

图2 myrandplottest对象

每个接口都有对应128位的IID加以标识,保证了全局唯一性,例如自定义的接口Imyrandplottest:

对象myrandplottest有自身128位的CLSID进行标识:

所创建的myrandplottest对象实现过程如下.

首先通过CoCreateInstance()函数来创建对象.其内部实际上也调用了CoGetClassObject函数,通过该函数,在注册表中找到通过Matlab生成的的DLL文件,将它装载在C++进程中,再调用DLL模块的DLLGetClassObject引出函数创建类厂,并将类厂对象接口指针返回给CoGetClassObject函数,再把类厂对象接口指针返回给CoCreateInstance()函数,然后就可以调用类厂的对象创建函数,类厂就创建我们想要的COM对象,并将其返回给CoCreateInstance()函数,这样就可以直接调用COM对象了.

CoCreateInstance()函数是将通过类厂创建对象的过程封装起来了,所以只要指定所要创建的myrandplot对象类的CLSID和待输出的Imyrandplottest接口指针及接口ID,就可以通过调用得到对象接口指针,而不需要与类厂打交道.这样就省去了很多的编程烦恼[5].

在COM对象创建过程中,客户程序、COM库和进程内组件程序3者之间的顺序关系见图3.

图3 客户程序调用COM库创建组件对象的顺序

该工程的运行结果见图4.

通过实例可以清楚地看到COM对象是如何创建和使用的,通过自定义的Imyrandplottest接口指针来获得Matlab绘制曲线的功能.

图4 运行结果

3.2 基于COM的力控组态软件的应用实现

下面以一个电厂锅炉汽包水位变化通知系统为例,分析C++是如何与力控组态软件实现双向通信的.首先通过力控组态软件创建一个组态工程,绘制了锅炉汽包的简单循环系统,在数据库中新建了一个注册点temp,作为与C++中的数据通信点.DbCommOcxEf控件就是一个已经封装好的COM组件,在运行程序之前,要保证DbCom.ocx已注册成功,确保控件可以被实现,它就相当于一个.dll文件被装入进程中.同样创建的CDbCommOcxEf对象类也有其128位的CLSID进行标识.

CDbCommOcxEf对象类 :static CLSID const clsid={0x3310fa25,0xa027,0x47b3,{0x8c,0x49,0x10,0x91,0x07,0x73,0x17,0xe9}}

由于客户程序只要知道数据对象的IDataObject接口指针就可以直接访问数据对象了.有时候客户程序希望能够及时知道数据对象发生变化的信息,以便得到最新数据.比如锅炉水位变化通知系统,客户希望及时了解水位的变化情况,而不是一遍遍地去判断水位是否发生变化.

通过声明一个对象来获取所要的注册点的信息,把这些信息通过IDataObject接口指针存储在通报连接接收器对象内部,实现数据连通[1].当注册点信息发生变化时,消息映射机制找到对应的事件控制函数IAdviseSink::OnDataChange,通过它可以更新注册点在C++工程中的信息.这样就实现了数据对象的变化通知机制,该过程如图5所示.C++工程的运行结果如图6所示.

图5 客户程序与数据对象之间的通信过程

图6 C++工程运行界面

通过在力控界面内将注册点temp值改为1时,其运行界面如图7所示.此时会发现C++界面上的数据已发生相应的变化.

图7 力控运行界面

4 结语

通过对两个应用实例的分析,我们对COM底层操作的实现和数据变化通知机制有了深入的了解.此外,COM技术不限制语言,不要求操作系统,更可以跨进程相互调用.客户程序可以很轻松地通过接口来调用对象提供的服务,而不必知道对象内部的实现细节,这就是COM技术给我们带来的好处.在未来软件发展过程中,COM技术将起到越来越大的作用.

[1]潘爱民.COM原理与应用[M].北京:清华大学出版社,2003:9-38.

[2]ROGERSON Dale.COM 技术内幕[M].杨秀章,译.北京:清华大学出版社,1999:12-37.

[3]SULLIVAN Kevin J,MARCHUKOV Mark ,SOCHA John.Analysis ofa conflictbetween aggregation and interface negotination in microsoft’s component object model[J].IEEE Transactions on Software Engineering,1999,25(4):584-599.

[4]张先刚,余金山.基于COM的数据访问组件的实现[J].计算机应用与软件,2005,22(9):17-20.

[5]曹晓阳,刘锦德.COM 及其应用向对象的组件集成技术[J].计算机应用1999,19(1):1-4.

猜你喜欢
调用组件对象
无人机智能巡检在光伏电站组件诊断中的应用
涉税刑事诉讼中的举证责任——以纳税人举证责任为考察对象
新型碎边剪刀盘组件
U盾外壳组件注塑模具设计
核电项目物项调用管理的应用研究
LabWindows/CVI下基于ActiveX技术的Excel调用
攻略对象的心思好难猜
基于系统调用的恶意软件检测技术研究
基于熵的快速扫描法的FNEA初始对象的生成方法
区间对象族的可镇定性分析