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來完成各種千奇百怪的接口實現方式,需要的只是想象力。
posted on 2007-04-30 11:37
michael 閱讀(695)
評論(0) 編輯 收藏 引用 所屬分類:
心得