15.COM 自动化原理

COM提供接口IDispatch,中文一般译作自动化接口,其实感觉直译为分派接口更好理解。自动化,顾名思义一开始诞生就是为了实现自动化的功能,支持各种脚本语言来调用接口工作。前面说了C++的接口都是指针,基于虚表的,而脚本语言没有指针也没法向COM传递参数调起指定函数。那么如何才能让脚本语言如Js来调用COM完成指定功能呢,他们间的参数如何传递,如何调起对应的程序,这都是COM 自动化的功能。


1.IDispatch接口原理

在介绍IDispatch接口前,先思考一个问题,脚本语言如何才能调起C++的接口工作呢?

其实根本上和普通接口一致,我们提供了IDispatch接口,JS语言本身不支持指针,但是JS引擎是可以自由实现的——在JS中调用具体的方法或属性,对应的名字传给JS引擎,JS引擎使用名字作为参数,调用IDispatch Invoke函数即可完成对应的调用操作。IDispatch接口相当于在脚本引擎和自实现的COM组件间规定了一个标准的调用接口。

除此之外,使用IDispatch接口的最大好处在于最大化程度的解耦实现和调用,程序的灵活性大大增强。比如之前我们需要根据输入调用COM组件中指定函数时,必须各种分支判断,获得对应的接口,再调用接口中对应函数才行;而使用IDispatch接口,只需要传入的方法名传给Invoke函数即可,相当于实现了脚本语言中的eval函数,大大增强了编译类语言的灵活性。

调用IDispatch接口时,既可以直接调用接口成员函数,也可通过Invoke传入方法名称和参数,所以这个接口也称作双接口,对应IDL关键字为dual

IDispatch定义如下:

IDispatch : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 
        /* [out] */ UINT *pctinfo) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( 
        /* [in] */ UINT iTInfo,
        /* [in] */ LCID lcid,
        /* [out] */ ITypeInfo **ppTInfo) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( 
        /* [in] */ REFIID riid,
        /* [size_is][in] */ LPOLESTR *rgszNames,
        /* [range][in] */ UINT cNames,
        /* [in] */ LCID lcid,
        /* [size_is][out] */ DISPID *rgDispId) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE Invoke( 
        /* [in] */ DISPID dispIdMember,
        /* [in] */ REFIID riid,
        /* [in] */ LCID lcid,
        /* [in] */ WORD wFlags,
        /* [out][in] */ DISPPARAMS *pDispParams,
        /* [out] */ VARIANT *pVarResult,
        /* [out] */ EXCEPINFO *pExcepInfo,
        /* [out] */ UINT *puArgErr) = 0;
    
};

其中:

1.GetTypeInfoCount中指明pctinfo=1为有返回类型库,0为没有

2.GetTypeInfo 获得当前的类型库中指定接口的类型信息接口指针

3.GetIDsofNames 获得指定名称的对应分派ID

4.Invoke传入指定的函数名称或分派ID,调用指定功能


2.IDispatch接口实现

IDispatch接口实现很灵活:

1.不使用类型库

GetTypeInfoCount和GetTypeInfo不需要实现,GetTypeInfoCount中指明pctinfo=1;GetIDsofNames和Invoke一般要求实现,必须要时连GetIDsofNames也可不用实现。不使用类型库的时候,实现GetIDsofNames和Invoke主要是靠查表。

GetIDsofNames传入Name值即可返回对应的ID

Invoke传入指定的ID 查表调用对应的函数实现逻辑

MFC中IDisaptch的实现,主要依靠自己查表的方法,后文将演示。

2.使用类型库

四个函数均需要实现。

使用类型库,实际上就是将表内容用类型库表示且提供更加丰富的信息。由类型库查询得到信息再调用是相当复杂的过程,所以COM库提供了标准的实现。

我们只需要使用LoadRegTypeLib和LoadTypeLib加载对应的类型库得到ITypeLib接口,再查询得到对应的接口的ITypeInfo接口,借助ITypeInfo接口我们即可完成对应IDispatch函数的实现。

ATL中IDisaptch的实现,主要依靠类型库的方法,后文将演示。


原创,转载请注明来自http://blog.csdn.net/wenzhou1219

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值