一般的通讯方式:
客户 <==> COM(vbtl)接口 <==> COM组件
自动化通讯方式:
客户(自动化控制器) <==> IDispatch::Invoke <==> 调度接口(或vbtl接口) <==> 实现IDispatch接口的COM组件 (自动化服务器)
自动化服务器 : COM组件
自动化控制器 :COM客户
相关知识:IDispatch, 调度接口,双重接口,类型库,IDL, VARIANT, BSTR
调度接口(dispinterface) :IDispatch::Invoke的一个实现所能调用的函数集合,客户只能通过IDispatch::Invoke使用组件
COM(vbtl)接口(custome) : 一个指针,指向一个函数指针数组,数组前三个元素是 QueryInterface,AddRef和Release
双重接口(dual) :客户既可以通过调度接口(IDispatch::Invoke),也可以直接通过COM接口(vbtl调用)使用组件
一般C++程序直接使用抽象接口调用COM组件,而编译器会进行地址映射。例如:
pIX->Fx (msg) ;
实际会被编译成这样:
(*(pIX->vbtl [IndexOfFx]))(pIX, msg) ;
具体如下:
1. 获取Fx在虚函数表中的索引 IndexOfFx = 4
2. 获取Fx的函数地址 pAddressOfFx = pIX->vbtl [IndexOfFx]
3. 解引用,调用函数 (注意需要传入this指针) (*pAddressOfFx)(pIX, msg)
上面三步合成就是 (*(pIX->vbtl [IndexOfFx]))(pIX, msg) ;了
但问题在于像VB, Javascript等没有指针的概念,如何做到上面几步,获取vbtl中的函数指针呢?
可以编写一个C++分析器处理 (相当于加入了一个中间层)
中间层关键要处理三种信息 : 组件的ProgID, 函数名称,参数
这个中间层通过IDispatch接口实现,其原型: