C++类的动态组件化技术(7)
作者:佚名; 更新时间:2014-12-05

  3.1. 复杂类型的传入参数

  ATL接口方法获取一个接口指针参数后,如何将此接口指针转变为C++对象指针?对于ATL对象,可以直接取得m_pCPPObj变量,而接口指针却不能。所以,需要提供一种途径,从ATL接口指针获取ATL组件的m_pCPPObj变量值。

  我们的设计是,为每个ATL组件提供一个基接口ICPPObjSeeker,实现对绑定C++对象指针(即m_pCPPObj)的查询方法HandleCPPObj。任意ATL接口都从该基接口派生,都可以调用HandleCPPObj方法。

  在前文就生命周期管理进行讨论时,曾提到这样一种情况:客户创建了一个组件,然后送交集合型组件管理。在集合型组件获取外部创建的组件的同时,需要:

  l 取得后者的C++对象指针。集合型组件对元素组件管理的实质是通过集合型C++对象对元素的C++对象进行管理,而集合型ATL对象和元素ATL对象之间并没有直接联系

  l 修改新加入元素组件的维护标识

  因此,我们为ICPPObjSeeker接口添加PostCPPObj方法,用于实现以上功能。

  ICPPObjSeeker接口idl定义如下所示,因为ICPPObjSeeker接口和HandleCPPObj、PostCPPObj方法实际上都应用于内部,所以使用“hidden”属性对外隐藏:

  [

       object,

       uuid(1E9F7F79-936D-4680-9F8E-34A7DCCFF818),

       dual,

       hidden,

       helpstring("ICPPObjSeeker Interface"),

       pointer_default(unique)

  ]

interface ICPPObjSeeker : IDispatch

{

       [id(1), helpstring("取得C++对象的指针"), hidden]

              HRESULT HandleCPPObj([out, retval] long* pCPPObj);

       [id(2), helpstring("取得C++对象的指针,客户程序不再负责对C++对象生命周期的维护"), hidden]

              HRESULT PostCPPObj([out, retval] long* pCPPObj);

};

ICPPObjSeeker接口的方法可以放在CCPP2ATLTemplateBase模板基类中统一实现:

template <class T>

class CCPP2ATLTemplateBase :

{

              ……

       /**********************************************************

         HandleCPPObj函数,由ICPPObjSeeker接口定义,

         负责取得ATL接口中的C++对象指针

       **********************************************************/

       STDMETHODIMP HandleCPPObj(long *pCPPObj)

       {

              AFX_MANAGE_STATE(AfxGetStaticModuleState())

              *pCPPObj = (long)m_pCPPObj;

              return S_OK;

       }

       /**********************************************************

         PostCPPObj函数,由ICPPObjSeeker接口定义,

         负责取得ATL接口中的C++对象指针,

         同时标记对象为内部维护,客户不再负责对象的生命周期管理

       **********************************************************/

       STDMETHODIMP PostCPPObj(long *pCPPObj)

       {

              AFX_MANAGE_STATE(AfxGetStaticModuleState())

              *pCPPObj = (long)m_pCPPObj;

              if (m_bInnerManage == FALSE) {

                     m_bInnerManage = TRUE;

                     m_pCPPObj->m_pAssociATLUnk = this;

                     m_pCPPObj->m_pAssociATLUnk->AddRef();

              }

              return S_OK;

       }

       };

  现在,所有的接口都不再直接从IDispatch派生,而改从ICPPObjSeeker派生,因此,IDispatch的实现也应该在实现ICPPObjSeeker接口的同一级或下级中提供。为了包容IDispatch,我们将ATL模板基类稍作改动:

template <class T, class Q, const IID* piid, const GUID* plibid = &CComModule::m_libid>

class ATL_NO_VTABLE CCPP2ATLTemplateBase :

       public IDispatchImpl<Q, piid, plibid>

{

       ……

};

核心期刊快速发表
Copyright@2000-2030 论文期刊网 Corporation All Rights Reserved.
《中华人民共和国信息产业部》备案号:ICP备07016076号;《公安部》备案号:33010402003207
本网站专业、正规提供职称论文发表和写作指导服务,并收录了海量免费论文和数百个经国家新闻出版总署审批过的具有国内统一CN刊号与国际标准ISSN刊号的合作期刊,供诸位正确选择和阅读参考,免费论文版权归原作者所有,谨防侵权。联系邮箱:256081@163.com