ATL接口映射宏详解[7]

六、COM_INTERFACE_ENTRY_AGGREGATE_BLIND 参ATL例程COMMAP

  上一节我们讲了COM_INTERFACE_ENTRY_AGGREGATE,这节要介绍的宏与它很类似。

#define COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)/
    {NULL,/
    (DWORD)offsetof(_ComMapClass, punk),/
    _Delegate},

  从定义上就可以看出,它与上一节介绍宏的唯一区别就在于,它没有指明接口ID!!
  所以在它的定义中第一项也是NULL。

  这个宏的用法与我们COM_INTERFACE_ENTRY_AGGREGATE一模一样。大家可以参考上一节内容以及ATL的例程COMMAP。

  我们来看看AtlInternalQueryInterface()中的相关代码。

ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis,
    const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
{
    //如果是IUnknown,....
    while (pEntries->pFunc != NULL)
    {
        BOOL bBlind = (pEntries->piid == NULL);
        if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
        {
            if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
            {
                ATLASSERT(!bBlind);
                IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw);
                pUnk->AddRef();
                *ppvObject = pUnk;
                return S_OK;
            }
            else
            {
                HRESULT hRes = pEntries->pFunc(pThis, iid, ppvObject, pEntries->dw);
                if (hRes == S_OK || (!bBlind && FAILED(hRes))) return hRes;
            }
        }
        pEntries++;
    }
    return E_NOINTERFACE;
}

  注意变量bBlind:

  BOOL bBlind = (pEntries->piid == NULL);

若没指定接口ID,也继续执行后面的操作,可见即使并非我们所需要的IID,也会执行_Delegate.
  从上可见,这个宏适用于一个聚集组件有多个接口的情况,这样只要是查询这个聚集组件的接口,就会进入_Delegate函数。但要特别注意的是这个宏的位置!! 比如若是这样的顺序:

BEGIN_COM_MAP
    COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pUnkAggBlind.p)
    COM_INTERFACE_ENTRY(IOuter)
END_COM_MAP


  当查询IOuter接口时就会出错!!!

七、COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)

  先看看这个宏的定义:

#define COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)/
    {&iid,/
    (DWORD)&_CComCacheData</
        CComAggregateCreator< _ComMapClass, &clsid >,/
        (DWORD)offsetof(_ComMapClass, punk)/
        >::data,/
    _Cache},

先看看它的典型用法:

class CAutoAgg :
    public IDispatchImpl< IAutoAgg, &IID_IAutoAgg, &LIBID_AGGREGLib >,
    public ISupportErrorInfo,
    public CComObjectRoot,
    public CComCoClass< CAutoAgg,&CLSID_CAutoAgg >
{
    ......
};

与一般的组件并无二样。

class COuter :
    public CChainBase,
    public IDispatchImpl,
    public CComCoClass
{
    BEGIN_COM_MAP(COuter)
        COM_INTERFACE_ENTRY_AUTOAGGREGATE(IID_IAutoAgg, m_pUnkAutoAgg.p, CLSID_CAutoAgg)
    END_COM_MAP()

    CComPtr m_pUnkAutoAgg;
};

  与宏COM_INTERFACE_ENTRY_AGGREGRATE(_)不同,COuter不用在FinalConstruct中创建聚集组件。外部组件会自动创建聚集组件!!!

1。

template < class Creator, DWORD dwVar >
_ATL_CACHEDATA _CComCacheData< Creator, dwVar >::data = {dwVar, Creator::Creat eInstance};

2。

static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD dw)
{
    HRESULT hRes = E_NOINTERFACE;
    _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw;
    IUnknown** pp = (IUnknown**)((DWORD)pv + pcd->dwOffsetVar);
    if (*pp == NULL) hRes = pcd->pFunc(pv, IID_IUnknown, (void**)pp);
    if (*pp != NULL) hRes = (*pp)->QueryInterface(iid, ppvObject);
    return hRes;
}

3。

template < class T, const CLSID* pclsid >
class CComAggregateCreator
{
public:
    static HRESULT WINAPI CreateInstance(void* pv, REFIID/*riid*/, LPVOID* ppv )
    {
        ATLASSERT(*ppv == NULL);
        ATLASSERT(pv != NULL);
        T* p = (T*) pv;
        return CoCreateInstance(*pclsid, p->GetControllingUnknown(), CLSCTX_ALL, IID_IUnknown, ppv);
    }
};

  因为_Cache,_CComCacheData,CComAggregateCreator这几个类和函数我们已经在前面见过或者见过类似的,所以就不再多讲了。总之我们可以看到,若m_pUnkAutoAgg.p不为空则直接查询,否则创建聚集组件。

  与宏COM_INTERFACE_ENTRY_AGGREGATE相比,这个宏似乎更好一些,仅当需要时才会创建,使用更简单。

   八、COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND( punk, clsid )

  看看它的定义:

#define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)/
    {NULL,/
    (DWORD)&_CComCacheData</
        CComAggregateCreator< _ComMapClass, &clsid >,/
        (DWORD)offsetof(_ComMapClass, punk)/
    >::data,/
    _Cache},

  呵呵,这个宏综合了 COM_INTERFACE_ENTRY_AUTOAGGREGATE() 和 COM_INTERFACE_ENTRY_AGGREGATE_BLIND() 的特点,既可以自动创建也可以很方便地查询聚集组件中的多个接口。不再赘述!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值