12.1.9 创建一个自动化组件的技巧
1.问题阐述
前面创建的COM对象都是定制接口对象,也就是所谓的前绑定。编译器在编译的时候装载类型库,分别使用了 #include 方法和 #import 方法来实现。装载了类型库后,编译器就知道如何编译接口函数的调用了。脚本语言是解释执行的语言,它在执行的时候不会知道具体的函数的地址,那么在脚本语言中,如何调用COM组件呢?
2.实现技巧
为了使脚本语言支持COM组件的调用,MS提供了另外一个接口,即Idispatch接口,又称为自动化接口,也被称为后绑定接口。自动化组件,即实现了Idispatch接口的组件。IDispatch接口用IDL形式说明如下:
[ interface IDispatch : IUnknown HRESULT GetTypeInfoCount([out] UINT * pctinfo); HRESULT GetIDsOfNames( // 根据函数名字,取得函数序号(DISPID) [local] //本地版函数 [call_as(Invoke)] //远程版函数 |
IDispatch接口有4个函数,解释语言的执行器就通过仅有的4个函数来执行组件所提供的功能。
其中GetIDsOfNames将读取一个函数的名称并返回其调度ID,又称为DISPID。DISPID并不是一个GUID,而只是一个长整数,它标识的是一个函数。对于IDispatch的每一个特定的实现,DISPID是唯一的。IDispatch的每一个实现都有其自己的IID。为执行某个函数,自动化控制程序将把DISPID传给Invoke成员函数。
Invoke可以将DISPID作为函数指针数组的索引,这一点同常规COM接口是相似的。但是自动化服务并不需要按此种方式实现Invoke。一个简单的自动化服务器可以根据DISPID用一个case语句执行不同的代码。IDispatch::Invoke将实现一组按索引来访问的函数,Invoke的一个实现所实现的函数集被称为一个调度接口,而COM接口是一个指向一个函数指针数组的指针,此数组的前3个元素分别是QueryInterface、AddRef及Release。Invoke函数参数含义:第一个参数是控制程序待调用函数的DISPID;第二个参数是保留值,必须为IID_NULL;第三个参数为保存位置信息;第四个参数为所指的调用函数的类型,它的值可以是DISPATCH_METHOD、DISPATCH_PROPERTYGET和DISPATCH_PROPERTYPUT值中的一个;第五个参数是传给被调用函数的参数;第六个参数是返回值。
3.实例代码
本实例演示如何创建双接口组件。启动ATL COM AppWizard,工程名为Object。选择DLL类型、不合并代理和存根代码、不支持MFC、不支持MTS。“New Atl Object”选择“Simple Object”,输入名称DFun,属性按默认设置,增加函数Add,如图12-7所示。
选择“Attributes”选项卡,设置双接口的属性如图12-8所示。
|
| 图12-7 双接口设置向导 |
|
| 图12-8 设置双接口属性 |
import "oaidl.idl"; [ [ |
Add([in] VARIANT v1, [in] VARIANT v2, [out, retval] VARIANT * pVal); |
/************************************************************************/ CComVariant v_1( v1 ); if((v1.vt & VT_I4) && (v2.vt & VT_I4) ) // 如果都是整数类型 pVal->vt = VT_I4; CComBSTR bstr( v_1.bstrVal ); pVal->vt = VT_BSTR; |
Set obj = CreateObject("Object.DFun") |
|
| 图12-9 调用COM接口中的 Lower函数 |
|
| 图12-10 调用 COM接口中 的Add函数 |
| 回书目 上一节 下一节 |



