COM组件技术探究
2017-03-21张春艳张海波
张春艳+张海波
摘要:COM Component(COM组件)技术是开发软件组件的方法,是微软公司为了解决软件复用,缩短软件开发时间而开发的一种新的软件开发技术。对COM组件的接口、COM组件的实现以及与普通DLL的区别进行了探究,以COM组件开发为研究视角,对COM组件开发的原理和方法进行分析,结合实例说明具体的开发步骤,并对COM组件在PHP上的调用方法做了具体示例。
关键词:COM;组件对象模型;接口
中图分类号:TP391 文献标识码:A 文章编号:1009-3044(2016)33-0096-03
Abstract: COM (Component Object Model) component technology is a method of developing software components. It is a new software development technology developed by Microsoft Corporation in order to solve software reuse and shorten software development time. This paper mainly discusses the interface of COM component, the realization of COM component and the difference between it and common DLL. It analyzes the principle and method of COM component development from the perspective of COM component development. Combined with an example to describes the specific development steps and calling the COM component on PHP.
Key words: COM; Component Object Model; Interface
1 概述
COM组件技术是一种十分完善的面向对象的技术规范。通常是以WIN32动态链接库(DLL)或可执行文件(EXE)的形式发布的可执行代码组成的,可以在跨平台条件下实现调用,对于代码重用有很大的意义。COM组件的核心思想是定义软件中可以重用的部分,实现代码复用。
COM组件的核心是组件和接口。其中组件是具有一定逻辑功能的可执行代码,而接口实现了对组件代码的封装与隔离。通常情况下一个有两个接口的COM组件如图1所示:
2 COM组件接口
COM组件最重要的部分是组件的接口。COM组件通过接口与外界进行联系,外界使用COM组件也必须知道COM组件的接口。因此COM组件的接口在系统中起着决定性作用。每个COM组件都必须有这三个接口:IUnknown、IClassFactory和IDispatch,其他接口都是直接或间接从这个接口派生而来。
2.1 基本接口
COM组件的基本接口是Iunknown接口,在COM组件中所有接口都以“I”开头。Iunknown接口的主要作用是对COM组件的所有接口进行标准化,以方便调用COM组件。COM组件的接口都必须符合一定的规范,在这个规范中规定任何一个接口都继承于Iunknown接口,這个接口主要有以下几个函数:
这里用struct定义Interface,由于struct关键字的成员属性为public,接口是用来与外界进行联系,接口的成员属性也应该为public。这里用_stdcall标记的函数将使用标准的调用约定,用这个关键字修饰的函数的参数将以堆栈从右向左的顺序传递,也就是说这些函数将删除参数在函数返回到调用者之前。QueryInterface函数是对组件进行自我描述的关键字函数,通过这个函数,用户可以查询某个组件是否支持特定的接口。另外的AddRef和Release这两个函数实现了对组件调用次数的引用计数。通过使用这两个函数,使组件可以自己实现删除内存。在COM组件中将对引用计数这个值进行维护,当用户从COM组件中取得一个接口时,将这个值加一,当用户使用完这个接口时,这个值减一。当引用计数为零时,彻底将组件从内存中删除。AddRef函数用来对引用计数值加一,Release对引用计数的值减一。
2.2 接口IClassFactory
IClassFactory的作用是创建COM组件。每个组件都必须有一个与之相关的类厂,由类厂创建组件实例,然后把实例指针交给客户程序。IClassFactory最重要的一个函数就是CreateInstance,类厂就是通过调用这个函数创建组件实例的。但是一般情况下不会直接调用它,通过API函数CoCreateInstance进行调用。
2.3 IDispatch调度接口
IDispatch接口也继承于IUnknown接口,对组件执行调度任务。由于COM组件是通过虚函数表来实现对函数的调度的,也就是说COM组件必须使用指针来实现对函数的调度,但是并不是所有的语言都支持指针,因此调度接口就是用来解决这一问题。在调度接口中,将组件的每个函数以及每个属性都进行相应的编号,在客户程序要调用这些函和属性的时候就把这些编号传给IDispatch 接口,再根据这些编号调用相应的函数。
3 COM组件的实现
按照组件在运行时所处的位置,它可分为进程内服务器和进程外服务器,其中进程外服务器又分为本地服务器和远程服务器。进程内服务器是指服务器和客户在同一进程空间中运行的服务器。它是以DLL形式封装的COM组件。以EXE封装的组件叫做进程外组件。
3.1 以动态链接库的形式实现
COM组件可以以动态链接库的形式实现,DLL格式的COM组件可以共享其链入的应用程序的地址空间,方便客户访问函数的指针列表。
3.2 以可执行程序的形式实现
在某些情况下,需要用EXE来实现组件,使EXE可以向外界提供自己擅长的服务功能,客户可以通过接口实现自己很难完成的任务,客户还可以通过接口控制应用程序,更灵活更有效的实现EXE的功能。
在EXE中实现组件和在DLL中实现组件主要有两个区别,一是EXE提供的组件将与客户程序不在同一进程中,这需要用到代理/残根机制来完成在跨进程的调用中参数的调整。二是EXE不像DLL,它是主动的,可以对自己的生命期进行控制。
4 COM组件与普通DLL的区别
COM组件与DLL都是为解决代码重用设计的,然而两者却有很多不同。COM组件便于升级维护功能扩充,有很好的安全性,可以轻松的实现进程间调用,具有封装、继承、多态的面向对象的特征,而DLL在这些方面都有很大不足。64位的系统不能调用32位的DLL,而将DLL封装成COM组件就可以被64位系统调用了。两者最大的区别是COM组件是以接口方式提供给用户的一种二进制的使用规范,而DLL是以函数集合的方式提供给用户进行调用。
在开发难度上COM组件相对DLL要更为复杂,它需要满足规范,是相对独立的模块,可以被其他语言调用,而DLL开发简单可移植性差,在调用上没有COM组件简单。
5 COM组件在PHP上的应用
在Windows平台下,PHP提供了内置的COM功能,利用PHP的COM类可创建有关组件对象的实例,基本格式如下:
$obj =new COM(“ProgID”);
其中COM为类名,ProgID为组件对象名,$obj为组件对象的实例变量。通过实例变量并使用“->”运算符,即可引用组件对象的有关属性、集合与方法。若将实例对象赋值为空(NULL),即可清除相应的对象实例。
下面通过笔者所做的基于COM组件在PHP上调用的实例来说明开发COM组件的过程以及在PHP上调用的方法。
首先打开Visual C++或者Visual Studio新建空白解决方案,添加新建项目,选择ATL项目,选择动態链接库(DLL)选项。打开类视图,添加类,选择ATL简单对象,进入ATL简单对象向导后,就可以设置对象名称,这里我设置的是Fun。在第一个空白框内填写对象名称,其他框会自动填写。
运行网页显示:Hello PHP 2016。调用成功。
在这个基础上,我们可以开发更复杂的COM组件,不过还需要对COM组件接口更深一步的研究。
6 结束语
通过对COM组件技术的研究,可以知道COM组件在使用中有很多优点。COM组件可以很好的实现代码重用,提高软件的复用率,而且也可以增强软件的可靠性,编程者可以跨语言调用COM组件,使用不同的语言开发也不会有影响,而且方便开发者在不同的环境中对COM组件进行调用,不用考虑32位还是64位系统的问题,这些优点都极大的提高软件的开发速度,降低开发成本。然而对COM组件的接口复杂性以及兼容性问题的研究还需要进一步进行研究。随着COM组件技术的不断完善,COM技术的应用将会更加广泛。
参考文献:
[1] 潘恒.中间件技术——COM组件的探究[J].科协论坛,2011(4):61-62.
[2] 赵海春.COM组件的设计与使用 [J].邵阳学院学报:自然科学版,2009,6(1):58.
[3] 孔梦荣,郑秋生,杜献峰.COM 组件技术探究[J].中原工学院学报,2004,15(2):22- 23,70.
[4] 潘爱民.com原理与应用[M].北京:清华大学出版社,2000.