COM高级应用-Automation(自动化)已是昨日黄花不再"高级"?

来源:互联网 发布:linux安装字体 ttc 编辑:程序博客网 时间:2024/06/10 06:06

在开发过程中,为提高内聚减少偶合,为系统的扩展性和维护性,通常都需要将不同的功能模块进行分离,即模块化,

对于模块化,除了以传统的DLL方式外,应用COM组件方式构件系统应该是最佳选择.

Automation自动化被作为COM组件技术的高级应用,在这,结合对其粗浅应用,简单说说Automation(自动化).温习的同时也希望能给初学者有点参考价值.

 

为方便说明自动化/普通的COM/普通的DLL三者的区别,先看看以下调用关系示意图,

 

创建自动化:

首先是创建自动化组件F1.DLL,其.创建过程可以依照MFC向导,一步步即可,其中有步需要勾选"Automation".向导完后,就可以申明和定义接口.然后编译注册就可以供外部调用

调用自动化:

客户调用上述自动化组件时,在客户模块中建立"自动化对象(F1.dll)"的代理类,其创建是通过类向导中的"Automatioin"选项页导入自动化组件以生成"接口代理(封装)类","接口"指的是自动化组件中定义的接口.

根据向导自动生成代理类后,注意下代理类的成员,就会发现自动化接口申明的所有方法都在其代理类中有原份拷贝.
有了这一代理类后,客户程序就可以直接调用自动化对象所申明的接口,
而不需要自动化DLL的任何接口或类型信息文件(这就是与普通COM组件区别所在).完全断开了自动化接口类型信息!

相比,客户对通常的COM组件调用,需要通过#import方式依靠编译器从DLL中导出并生成相应的.h或.tlb文件,该文件包含COM接口的GUID及其他相关类型信息.

#import "dll" 这一命令,实际上客户程序在编译器的帮助下,完成了类似于大家熟悉的include<*.h>操作.

这也就是自动化技术与普通COM组件的区别及奥妙之处.

用过COM的,可能会疑问,没有类型信息或在内存中生成虚表,那客户程序到底怎么实现动态晚期绑定?

其实,自动化组件绑定时期,比通常所说的动态晚期绑定还要晚,

大家都知道,通常COM是通过内存中的虚表(函数指针数组)来绑定.

而这个虚表,实际上,由编译器在编译过程中根据COM接口的相关信息悄悄构建。

值得注意的是:

编译器在编译过程中,遇到接口的函数调用时,实际上,将函数调用替换成:“虚表指针 + 索引号”。

索引号就是函数所在虚表的位置。这样,接口的函数调用就在编译时被绑定到虚表的某一个位置,只是直到运行时,才知道索引号所对应虚表的位置内的“实际存放的函数指针值”。

以上,COM接口的函数晚期绑定,与自动化对象相比,应该算是“早绑定”。

甚至也可以认为,在调用自动化接口的函数时,在编译时压根就不需要绑定,也就是,绑定不是由编译器完成,而是在运行时根据函数名由自动化对象自身所定义的方法去完成绑定过程。只要给个字符串(函数名),绑定过程由自己的代码来完成,这就是自动化的特别及奥妙所在。

所以,调用自动化接口函数时,其绑定过程,不是通过编译器也不是通过虚表,而是在运行时通过其函数名(字符串)或索引号(整型数)传给自身的方法去完成.

客户程序只要通过代理类知道几个字符串(即:组件名\接口名\函数名)就可以实现自动化调用.

这样,调用起来比常说的COM组件方便多了,也不需要知道GUID或接口类型,不需要其他类型信息文件.

这一特性,为开发提供了很大灵活性.也由此,自动化也成为真正跨编译环境调用.也为脚本非编译语言调用COM提供方便.

至于自动化为何能通过名字(字符串)绑定函数,对此,可以参考<COM原理及应用>一书,讲得很详尽.

以上,只是简单原理,其实际实现过程在此简略.

自动化完后,再来说说普通COM的运用:

上图中,自动化又调用COM组件,其调用是通过#import方式引入,
#import的作用实际上就是依靠编译器创建了被引入COM组件的类型信息文件(.h或.tlh后缀).

引入外部组件信息后,通过智能指针CComQIPtr<接口名,接口GUID>,加载组件.如:
申明所调用接口的智能指针(智能指针为方便接口引用记数的管理):
CComQIPtr <IXXX接口名, &IID_IXXXX接口GUID> m_pIMyInterFace;
加载并创建组件对象:
m_pIMyInterFace.CoCreateInstance(CLSID_XX/*组件对象GUID,一个COM组件可以包括多个组件类(后对象)*/, NULL, CLSCTX_INPROC_SERVER);

以上出现的“IXXX接口名”、“IID_IXXXX接口GUID”、“CLSID_XX组件对象GUID”等都是通过“#import ”引入。

另外说明:
CComQIPtr<> 和 CComPtr<>这两个类都在 <atlbase.h> 中声明。
CComQIPtr<> 包含了 CComPtr<>的所有功能,因此可以完全用 CComQIPtr<> 来使用智能接口指针,
完成接口引用记数的自动管理.CComQIPtr<> 唯一的缺点就是不能定义 IUnknown * 指针。
CComQIPtr必须要两个模板参数:一个是被操纵接口类型 ,另一个是对应于这个接口的GUID.

也可以通过一个已知接口得到另一个接口:
CComQIPtr <IXXXX, &IID_IXXXXX>   pIXXXX(m_pIXXXXX);

普通DLL(略).

 

以上,错之处,请斧正.

原创粉丝点击