9.ATL实现IDispatch自动化接口

来源:互联网 发布:广西老年大学网络报名 编辑:程序博客网 时间:2024/06/06 13:18

在一般情况下,简单的IDispatch接口我们可以不依赖类型库来完成,但是对于分发函数比较多或是需要具体类型信息的场合,还是需要使用类型库来实现IDispatch接口。


1.通用的依赖类型库实现IDispatch

前面讲了在ATL中使用类型库创建接口的方法,这里以ATL来演示通用的借助类型库实现IDispatch接口的过程。但是实际上只要提供类型库,在MFC中也可以使用此方法。

编辑类型库,声明一个接口继承自IDispatch

[object,uuid(CA00179E-7AD8-4C6D-8544-23A571C31D8C),dual,nonextensible,helpstring("ICat 接口"),pointer_default(unique)]interface ICat : IDispatch{[id(1)] HRESULT SayHello1([in] BSTR szWord);[id(2)] HRESULT SayHello2([in] int nAge);};
注意这里声明为双端接口dual,在双端接口下既可通过Invoke调用方法也可以通过直接获取接口调用对应的方法,兼顾了脚本语言的易用性和编译语言的性能。


ATL使用多重继承实现COM,所以声明COM组件对象如下:

class ATL_NO_VTABLE CAnimalObject :public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<CAnimalObject, &CLSID_AnimalObject>,public ICat


这里声明一个类型信息接口指针ITypeInfo* m_pITI;,具体实现如下:

自定义函数加载类型库,导出对应的信息接口指针

HRESULT CAnimalObject::MyLoadTypeLib(LCID lcid, ITypeInfo **ppTInfo){HRESULThr=E_FAIL;ITypeLib*pTypeLib=NULL;if (ppTInfo==NULL){return E_POINTER;}*ppTInfo = NULL;if (m_pITI==NULL){//加载Type Libhr = LoadRegTypeLib(LIBID_AtlDispatchLib, 1, 0, lcid, &pTypeLib);if (FAILED(hr)){hr = LoadTypeLib(OLESTR("AtlDispatch.tlb"), &pTypeLib);}if (FAILED(hr)){return hr;}//导出TypeInfo接口hr = pTypeLib->GetTypeInfoOfGuid(IID_ICat, &m_pITI);pTypeLib->Release();if (FAILED(hr)){return hr;}}*ppTInfo = m_pITI;m_pITI->AddRef();OutputDebugString(L"类型库加载成功");return S_OK;}

存在类型库,所以GetTypeInfoCount实现如下:

HRESULT STDMETHODCALLTYPE CAnimalObject::GetTypeInfoCount( /* [out] */ __RPC__out UINT *pctinfo){*pctinfo = 1;//存在类型库return S_OK;}

GetTypeInfo、GetIDsOfNames、Invoke均借助于ITypeInfo接口,如下:

HRESULT STDMETHODCALLTYPE CAnimalObject::GetTypeInfo( /* [in] */ UINT iTInfo,/* [in] */ LCID lcid,/* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo){if (0!=iTInfo)//0表示获取该接口实现的类型信息{return TYPE_E_ELEMENTNOTFOUND;}return  MyLoadTypeLib(lcid, ppTInfo);}HRESULT STDMETHODCALLTYPE CAnimalObject::GetIDsOfNames( /* [in] */ __RPC__in REFIID riid,/* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,/* [range][in] */ UINT cNames,/* [in] */ LCID lcid,/* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId){HRESULT hr = E_FAIL;ITypeInfo* pTypeInfo=NULL;if (riid!=IID_NULL)//riid为保留参数,必须为IID_NULL{return DISP_E_UNKNOWNINTERFACE;}//借用类型库完成GetIDsOfNameshr = GetTypeInfo(0, lcid, &pTypeInfo);if (SUCCEEDED(hr) && pTypeInfo){hr = pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId);pTypeInfo->Release();}return hr;}HRESULT STDMETHODCALLTYPE CAnimalObject::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){HRESULT hr = E_FAIL;ITypeInfo* pTypeInfo=NULL;if (riid!=IID_NULL)//riid为保留参数,必须为IID_NULL{return DISP_E_UNKNOWNINTERFACE;}hr = GetTypeInfo(0, lcid, &pTypeInfo);if (FAILED(hr) || NULL==pTypeInfo){return hr;}//借用类型库完成Invokehr = pTypeInfo->Invoke((ICat*)this, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);if (FAILED(hr)){pTypeInfo->Release();return DISP_E_EXCEPTION;}pTypeInfo->Release();return hr;}

2.ATL中的实现IDispatch方法

ATL实现IDispatch接口非常简单,和上面的同样方法实现一样,只是IDispatch接口实现放在了类IDispatchImpl中,我们只要如下声明即完成了IDispatch接口。

class ATL_NO_VTABLE CAnimalObject :public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<CAnimalObject, &CLSID_AnimalObject>,public IDispatchImpl<ICat, &IID_ICat, &LIBID_AtlDispatchLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
是不是非常简单?

实际上,IDispatchImpl做的事情和我们之前的方法一模一样,只是微软做了个封装而已,如果感兴趣可以自行阅读源码。


3.调用IDispatch接口

类似MFC中借助COleDispatchDriver类简化Invoke函数调用,ATL中借助CComDispatchDriver类来简化Invoke函数调用,如下:

//初始化COM库if (CoInitialize(NULL) != S_OK){wcout << L"Fail to Initialize COM" << endl;return -1;}//自动化调用CComDispatchDriver d;   if (SUCCEEDED(d.CoCreateInstance(CLSID_AnimalObject))){CComVariant p1;  p1.vt = VT_BSTR;  p1.bstrVal = SysAllocString(L"毛毛");CComVariant p2;  p2.vt = VT_I4;  p2.lVal = 12;  d.Invoke1(1, &p1, NULL);d.Invoke1(2, &p2, NULL);d.Release();}::CoUninitialize();


IDispatch ATL实现方法下载链接

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

0 0
原创粉丝点击