ATL对接口查询的支持

ATL对接口查询的支持

COM对象实现接口的方法是多种多样的,常用的有多重继承、聚合、tear-off等。为了最大限度地支持接口查询的多样性,ATL使用表驱动的方式来管理接口查询,以做到代码封闭和扩展灵活,表条目格式为:

struct  _ATL_INTMAP_ENTRY
{
    
const  IID *  piid; 
    DWORD_PTR dw;
    _ATL_CREATORARGFUNC
*  pFunc; 
};


piid是接口ID,dw为自定义参数,pFunc是自定义函数的地址。在QueryInterface时,ATL调用pFunc,并将dw传给pFunc,pFunc可以根据自己的需要解析dw,获得查询必需的信息。ATL预提供了一些函数来处理上述常用的查询请求,如_Creator、_Delegate等,它们被放置于CComObjectRootBase中。

(1)多重继承
           ATL并没有提供支持多重继承的函数,而是将pFunc设置为_ATL_SIMPLEMAPENTRY宏,将dw设为父类子对象在子类对象中的偏移量,当搜索表时发现pFunc为_ATL_SIMPLEMAPENTRY时,便直接使用偏移量相加获得结果。

            if  (pEntries -> pFunc  ==  _ATL_SIMPLEMAPENTRY) 
            {
                IUnknown *  pUnk  =  (IUnknown * )((INT_PTR)pThis + pEntries -> dw);
                pUnk
-> AddRef();
                
* ppvObject  =  pUnk;
                
return  S_OK;
            }

         接口映射表项宏为:

         #define  COM_INTERFACE_ENTRY(x)\
             {
& _ATL_IIDOF(x), \
             offsetofclass(x, _ComMapClass), \
             _ATL_SIMPLEMAPENTRY},


(2)聚合
           ATL使用_Delegate函数来支持聚合,此时dw存储的是内部对象指针成员变量在外部对象中的偏移量,_Delegate利用此偏移量获得内部对象指针,然后将查询调用委托给它。

    static  HRESULT WINAPI _Delegate( void *  pv, REFIID iid,  void **  ppvObject, DWORD_PTR dw)
    {
        HRESULT hRes 
=  E_NOINTERFACE;
        IUnknown
*  p  =   * (IUnknown ** )((DWORD_PTR)pv  +  dw);
        
if  (p  !=  NULL)
            hRes 
=  p -> QueryInterface(iid, ppvObject);
        
return  hRes;
    }
   
         接口映射表项宏为:

      #define  COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\
          {
& iid,\
          (DWORD_PTR)offsetof(_ComMapClass, punk),\
          _Delegate},
   
(3)tear-off
           ATL使用_Creator函数来支持tear-off,此时dw中存储的是一个静态_ATL_CREATORDATA结构的地址,_Creator利用其中的指向创建函数的指针创建一个tear-off对象。
                  
         static  HRESULT WINAPI _Creator( void *  pv, REFIID iid,  void **  ppvObject, DWORD_PTR dw)
         {
              _ATL_CREATORDATA
*  pcd  =  (_ATL_CREATORDATA * )dw;
              
return  pcd -> pFunc(pv, iid, ppvObject);
         }

         接口映射表项宏为:
            
      #define  COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)\
          {
& iid,\
          (DWORD_PTR)
& ATL::_CComCreatorData < \
              ATL::CComInternalCreator
<  ATL::CComTearOffObject <  x  >   > \
              
> ::data,\
          _Creator},

      _ComCreatorData的相关定义如下:
      
struct  _ATL_CREATORDATA
{
    _ATL_CREATORFUNC
*  pFunc;
};

template 
< class  Creator >
class  _CComCreatorData
{
public :
    
static  _ATL_CREATORDATA data;
};

template 
< class  Creator >
_ATL_CREATORDATA _CComCreatorData
< Creator > ::data  =  {Creator::CreateInstance};


      我们还可以定义自己的接口查询辅助函数和辅助数据,通过dw和pFunc来完成各种千奇百怪的接口实现方式,需要的只是想象力。

你可能感兴趣的:(ATL对接口查询的支持)