分享
 
 
 

COM复习(一) : COM复用的中Containment(包容)和Aggregation(聚合)的实现

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

Containment是一种比较简单的复用方法,如果Component B复用Component A,Component B实际上是Component A的一个客户,Component B向客户提供的Component A的功能实际上是Component B直接调用Component A完成的。当然Component B可以扩充Component A的功能。Component B可以直接使用已经存在的Component A,而不需要对Component A做任何改动。

Containment的例子实现略(潘爱民《COM原理与应用》第四章)

Aggregation则比较复杂,Component A必须能够适应被Aggregation下的特殊处理。其核心在于QueryInterface函数。Aggregation涉及到聚合对象和被聚合对象双方的协作,体现了真正意义上的COM复用,而Containment只是客户程序和Component的嵌套,这是Containment和Aggregation的本质区别。

Aggregation的实现(摘自潘爱民《COM原理与应用》)。

Component A的Code

class INondelegatingUnknown

{

public:

virtual HRESULT __stdcall NondelegationQueryInterface(const IID& iid, void **ppv) = 0 ;

virtual ULONG __stdcall NondelegatingAddRef() = 0;

virtual ULONG __stdcall NondelegationRelease() = 0;

};

class CA : public ISomeInterface, public INondelegatingUnknown

{

protected:

ULONG m_Ref;

public:

CA(IUnknown *pUnknownOuter);

~CA();

public :

// Delegating IUnknown

virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv) ;

virtual ULONG __stdcall AddRef() ;

virtual ULONG __stdcall Release() ;

// Nondelegating IUnknown

virtual HRESULT __stdcall NondelegationQueryInterface(const IID& iid, void **ppv);

virtual ULONG __stdcall NondelegatingAddRef();

virtual ULONG __stdcall NondelegationRelease();

virtual HRESULT __stdcall SomeFunction( ) ;

private :

IUnknown *m_pUnknownOuter; // pointer to outer IUnknown

};

// Implemention of class CA

CA::CA (IUnknown *pUnknownOuter)

{

m_Ref = 0;

g_CompANumber ++ ;

m_pUnknownOuter = pUnknownOuter;

}

CA::~CA()

{}

ULONG CA::NondelegatingAddRef()

{

m_Ref ++;

return (ULONG) m_Ref;

}

ULONG CA::NondelegationRelease ()

{

m_Ref --;

if (m_Ref == 0 )

{

g_CompANumber -- ;

delete this;

return 0;

}

return (ULONG) m_Ref;

}

HRESULT CA::NondelegationQueryInterface(const IID& iid, void **ppv)

{

if ( iid == IID_IUnknown )

{

*ppv = (INondelegatingUnknown *) this ;

((IUnknown *)(*ppv))->AddRef() ;

} else if ( iid == IID_SomeInterface )

{

*ppv = (ISomeInterface *) this ;

((ISomeInterface *)(*ppv))->AddRef() ;

}

else

{

*ppv = NULL;

return E_NOINTERFACE ;

}

return S_OK;

}

ULONG CA::AddRef ()

{

if ( m_pUnknownOuter != NULL )

return m_pUnknownOuter->AddRef();

else

return NondelegatingAddRef();

}

ULONG CA::Release ()

{

if ( m_pUnknownOuter != NULL )

return m_pUnknownOuter->Release ();

else

return NondelegationRelease();

}

HRESULT CA::QueryInterface(const IID& iid, void **ppv)

{

if ( m_pUnknownOuter != NULL )

return m_pUnknownOuter->QueryInterface(iid, ppv);

else

return NondelegationQueryInterface(iid, ppv);

}

HRESULT CA::SomeFunction()

{

printf("This is CA::SomeFunction!\n");

return S_OK;

}

由上面的代码可以看出,被聚合的对象需要实现两个IUnknown接口,Delegation Unknown和NonDelegation Unknown接口,NonDelegation Unknown是按正常方式实现的IUnknown接口。Delegation Unknown在非Aggregation使用时候直接把所有调用传给NonDelegation Unknown接口;而在Aggregation下,它把调用传给外部对象的接口,而此时外部对象通过NonDelegation接口对内部对象进行控制。

Aggregation下CAFactory的CreateInstance实现:

HRESULT CAFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv)

{

HRESULT hr;

// iid must be IID_IUnknown for aggregating

if ( ( pUnknownOuter != NULL ) && ( iid != IID_IUnknown ) )

{ return CLASS_E_NOAGGREGATION; }

*ppv=NULL;

hr=E_OUTOFMEMORY;

//Create the object passing function to notify on destruction.

CA *pObj=new CA (pUnknownOuter);

if (NULL==pObj) return hr;

//Obtain the first interface pointer (which does an AddRef)

hr = pObj->NondelegationQueryInterface(iid, ppv);

if (hr != S_OK) {

//Kill the object if initial creation or FInit failed.

g_CompANumber --; // Reference count g_CompANumber be added in constructor

delete pObj;

}

return hr;

}

MFC的COM Aggregation实现:COM使用了C++嵌套类来实现COM接口,并且使用接口映射表来简化编程工作,MFC对COM的支持是从类CCmdTarget开始。

#define DECLARE_INTERFACE_MAP() private: static const AFX_INTERFACEMAP_ENTRY _interfaceEntries[]; protected: static const AFX_INTERFACEMAP interfaceMap; static const AFX_INTERFACEMAP* PASCAL GetThisInterfaceMap(); virtual const AFX_INTERFACEMAP* GetInterfaceMap() const; struct AFX_INTERFACEMAP_ENTRY

{

const void* piid; // the interface id (IID) (NULL for aggregate)

size_t nOffset; // offset of the interface vtable from m_unknown

};

struct AFX_INTERFACEMAP

{

#ifdef _AFXDLL

const AFX_INTERFACEMAP* (PASCAL* pfnGetBaseMap)(); // NULL is root class

#else

const AFX_INTERFACEMAP* pBaseMap;

#endif

const AFX_INTERFACEMAP_ENTRY* pEntry; // map for this class

};

由此可以很明显看出,MFC继续使用Map表来实现COM接口。查看具体的Map表的增加和删除宏可以更详细的了解架构。

#define BEGIN_INTERFACE_MAP(theClass, theBase) const AFX_INTERFACEMAP* PASCAL theClass::GetThisInterfaceMap() { return &theClass::interfaceMap; } const AFX_INTERFACEMAP* theClass::GetInterfaceMap() const { return &theClass::interfaceMap; } AFX_COMDAT const AFX_INTERFACEMAP theClass::interfaceMap = { &theBase::GetThisInterfaceMap, &theClass::_interfaceEntries[0], }; AFX_COMDAT const AFX_INTERFACEMAP_ENTRY theClass::_interfaceEntries[] = { #define INTERFACE_PART(theClass, iid, localClass) { &iid, offsetof(theClass, m_x##localClass) }, #define INTERFACE_AGGREGATE(theClass, theAggr)

{ NULL, offsetof(theClass, theAggr) }, #define END_INTERFACE_MAP() { NULL, (size_t)-1 } }; 其中,offsetof宏可以给出成员变量与分类之间的偏移量,编译器在编译时候计算这个常数。

而接口部分定义则使用宏BEGIN_INTERFACE_PART、INIT_INTERFACE_PART、END_INTERFACE_PART进行定义。

#define BEGIN_INTERFACE_PART(localClass, baseClass) class X##localClass : public baseClass { public: STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj); #define INIT_INTERFACE_PART(theClass, localClass) size_t m_nOffset; INIT_INTERFACE_PART_DERIVE(theClass, localClass) #define INIT_INTERFACE_PART_DERIVE(theClass, localClass) X##localClass() { m_nOffset = offsetof(theClass, m_x##localClass); } #define END_INTERFACE_PART(localClass) } m_x##localClass; friend class X##localClass; 复习二将重点涉及COM一些高级概念,从Marshal到Thread Model(Apartment和Free)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有