ATL接口映射宏详解[7]

原创 2004年07月19日 11:19:00
六、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() 的特点,既可以自动创建也可以很方便地查询聚集组件中的多个接口。不再赘述!!

ATL接口映射宏详解[7]

七、COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid) 参ATL例程COMMAP 先看看这个宏的定义: #define COM_INTERFACE_...
  • zougangx
  • zougangx
  • 2008年05月24日 22:41
  • 396

ATL接口映射宏详解

* 本文选自:COM集中营 ATL接口映射宏详解lostall 序言:     这几天看了看ATL的接口映射宏,不知不觉看得比较深入了,突然就萌发了把它写出来的想法。ATL中定义了很多接口映射宏,有几...
  • bluecrest
  • bluecrest
  • 2002年05月29日 10:35
  • 1084

ATL接口映射宏详解[2]

5:CComCreator::CreateInstance(void* pv, REFIID riid, LPVOID* ppv) { T1* p = NULL; ATLTRY(p = new T1(...
  • zougangx
  • zougangx
  • 2008年05月24日 22:34
  • 451

ATL接口映射宏详解[1]

序言:   这几天看了看ATL的接口映射宏,不知不觉看得比较深入了,突然就萌发了把它写出来的想法。ATL中定义了很多接口映射宏,有几个还是比较重要的,虽然好象没有必要把它所有的细节都弄得很清楚,但深入...
  • zougangx
  • zougangx
  • 2008年05月12日 17:36
  • 447

ATL接口映射宏详解[2]

5: CComCreator::CreateInstance(void* pv, REFIID riid, LPVOID* ppv) {     T1* p = NULL;     ATLTR...
  • tofy
  • tofy
  • 2004年07月19日 11:12
  • 1231

ATL接口映射宏详解[5]

五.COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) 参ATL例程COMMAP 这一节中将介绍ATL中用于聚集对象的宏。聚集对象的概念请参阅其它参考书。 现在先看一看这...
  • zougangx
  • zougangx
  • 2008年05月24日 22:38
  • 414

ATL接口映射宏详解[4]

四.COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk) 参ATL例程COMMAP 这个宏与上一节所讲的COM_INTERFACE_ENTRY_TEAR_...
  • zougangx
  • zougangx
  • 2008年05月24日 22:37
  • 435

ATL接口映射宏详解[8]

九、COM_INTERFACE_ENTRY_CHAIN(classname) 参ATL例程COMMAP   先看看它的定义: #define COM_INTERFACE_ENTRY_CHAIN...
  • tofy
  • tofy
  • 2004年07月19日 11:20
  • 1057

ATL接口映射宏详解[3]

三、COM_INTERFACE_ENTRY_TEAR_OFF(iid, x) 参考ATL例程Beeper、COMMAP 使用这个宏的目的就是为了把一些很少用到的接口放在一个单独的组件中实现,仅 当查询...
  • zougangx
  • zougangx
  • 2008年05月24日 22:35
  • 440

ATL接口映射宏详解[6]

六、COM_INTERFACE_ENTRY_AGGREGATE_BLIND 参ATL例程COMMAP 上一节我们讲了COM_INTERFACE_ENTRY_AGGREGATE,这节要介绍的宏与它很类似...
  • zougangx
  • zougangx
  • 2008年05月24日 22:40
  • 384
收藏助手
不良信息举报
您举报文章:ATL接口映射宏详解[7]
举报原因:
原因补充:

(最多只允许输入30个字)