深入探索MS COM開發(fā)框架 之 MFC和ATL
By 81_redstar@163.com
------------------------------------------------------------------------------------------------------------------------------
文章索引:
一、概述和待剖析宏羅列
二、MFC、ATL COM支持原理概述
三、宏剖析
☆ ☆ MFC篇
PART1----接口基礎(chǔ)構(gòu)造的由來
PART2 ----深入CCmdTarget看一看COM三大元素的實(shí)現(xiàn)
PART3------類廠的由來
PART4-------自動(dòng)化支持
PART5-------組件得以使用的紐帶:幾個(gè)核心函數(shù)
☆ ☆ ATL篇
PART1----幾個(gè)核心模板類介紹
PART2----模板撐起的天空 : 接口的由來
PART3-------自動(dòng)化支持
PART4------深入核心模板類
PART5-------組件得以使用的紐帶:幾個(gè)核心函數(shù)
---------------------------------------------------------------------------------------------------------------------------
COM是出了名的難纏.原因在于它本身的設(shè)計(jì)灌注了大量的細(xì)節(jié)處理,九曲十八彎,令人迷惑.
然而MS慣用的宏手法,也是令很多人迷惑、久久不得思路.那么MFC、ATL用宏手法來提供對
COM開發(fā)的支持,就更加令人…了.下面我們就進(jìn)程內(nèi)組件開發(fā)探討一下MFC、ATL對COM開
發(fā)的基礎(chǔ)支持是怎樣實(shí)現(xiàn)的….
一、概述和待剖析宏羅列
首先給你一個(gè)關(guān)于COM結(jié)構(gòu)大致的描述 : 在組件(dll,exe,ocx等)內(nèi),存在大量的組件類
(CoClass),每個(gè)組件類維護(hù)N多的接口(interface),接口背后維護(hù)N的方法.自然還有類廠
(ClassFactory),類廠是組件類的平行類.
不錯(cuò),那么MFC、ATL是怎樣將上述的結(jié)構(gòu)實(shí)現(xiàn)的呢 ?
針對MFC我們需要剖析的宏羅列于下:
存在組件類.h和.cpp文件中的宏:
1. DECLARE_DYNCREATE(CSAM)
IMPLEMENT_DYNCREATE(CSAM, CCmdTarget)[.cpp]
簡要說明:支持RTTI和動(dòng)態(tài)創(chuàng)建類對象能力.
關(guān)于此,下面不會(huì)詳細(xì)講解.
欲了解更多細(xì)節(jié)者可參見
《深入淺出MFC》,原理相同
2. DECLARE_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CSAM, CCmdTarget)[.cpp]
END_MESSAGE_MAP()
簡要說明:維護(hù)消息處理系統(tǒng),原因在于MFC仍然
以CwinApp對象為核心.
對于此,下面不會(huì)詳解,
欲知詳情,參考《深入淺出MFC》.
3.DECLARE_OLECREATE(CSAM)
IMPLEMENT_OLECREATE(CSAM, "MFCCOM.SAM",
0x43d242f9, 0x4f7e, 0x4cbb, 0xae, 0xda, 0x77, 0x8d, 0xa1, 0x16, 0xd0, 0xd9)
簡要說明:創(chuàng)建類廠對象,且將類廠和組件類關(guān)聯(lián),
為通過CLSID創(chuàng)建類實(shí)例提供保證.
4.DECLARE_DISPATCH_MAP()
BEGIN_DISPATCH_MAP(CSAM, CCmdTarget)[.cpp]
END_DISPATCH_MAP()
簡要說明:支持自動(dòng)化分發(fā),事實(shí)上,
這里體現(xiàn)MFC對COM支持的真正意圖,
因?yàn)镸FC默認(rèn)派生的接口為dispinterface
(純dispatch接口),具體細(xì)節(jié)下面會(huì)描述.
5.DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_MAP(CSAM, CCmdTarget)[.cpp]
INTERFACE_PART(CSAM, IID_ICOM, Dispatch)
END_INTERFACE_MAP()
簡要說明:創(chuàng)建接口映射表,這里的手法在MS的FrameWork中隨處可見
雖然可能細(xì)節(jié)的實(shí)現(xiàn)不同.
在dll主文件中的: [xxx.cpp]
1.AFX_MANAGE_STATE(AfxGetStaticModuleState())
簡要說明:這里是模塊的狀態(tài)管理.
很重要,它維護(hù)關(guān)于程序的
大量信息,我們將討論其中的類廠表.
2. COleObjectFactory::RegisterAll()
簡要說明:在dll初始化時(shí),注冊所有的類廠.
3. AfxDllGetClassObject(rclsid, riid, ppv);
簡要說明:根據(jù)rclsid獲取類廠指針.
幾個(gè)重要的函數(shù):
1. EnableAutomation()
簡要說明:存在于各組件類的構(gòu)造函數(shù)中
使得CcmdTarget內(nèi)含的xDiapatch首先獲得
另一個(gè)內(nèi)含的實(shí)現(xiàn)Idispatch的對象的vtable,
從而使得programmers自建的接口類成為真正的
實(shí)用品.
這里有點(diǎn)復(fù)雜,詳細(xì)的下面說明.
2. AfxOleLockApp()
簡要說明:存在于各組件類的構(gòu)造函數(shù)中
自然這個(gè)組件類須是Creatable By ID的
才會(huì)顯式.
創(chuàng)建組件對象時(shí),鎖定App,進(jìn)入臨界區(qū).
3. AfxOleUnlockApp()
簡要說明: 存在于各組件類的構(gòu)析函數(shù)中
自然這個(gè)組件必須是Creatable By ID 的,
才會(huì)顯式.
退出臨界區(qū).
是否OLE 自動(dòng)化創(chuàng)建的所有對象銷毀,
是則終止應(yīng)用程序,在析構(gòu)函數(shù)中調(diào)用.
4. CCmdTarget::OnFinalRelease()
組件類對象的最后引用釋放后,進(jìn)行的收尾工作.
針對ATL我們需要剖析的宏羅列如下:
在組件類.h文件中的宏:
在.h文件中:
1. DECLARE_REGISTRY_RESOURCEID(IDR_SIM)
簡要說明:支持用注冊表腳本注冊組件,腳本
在ATL中作為資源的一種.
2.DECLARE_PROTECT_FINAL_CONSTRUCT()
簡要說明:防止組件類對象被刪除.
3.BEGIN_COM_MAP(CSim)
COM_INTERFACE_ENTRY(ISim)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
簡要說明:生成COM映射表,其作用與MFC的接口映射表作用是一樣的.
在.cpp文件中:[xxx.cpp]
5. BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Sim, CSim)
END_OBJECT_MAP()
簡要說明:生成組件類表,保存所有組件類的大量信息,包括
CLSID、組件類的類工廠、更新注冊成員函數(shù)的指針、
獲得描述成員函數(shù)的指針、創(chuàng)建組件類實(shí)例成員函數(shù)的指針等.
這里也是一個(gè)關(guān)鍵之所在.
我們發(fā)現(xiàn)上面的MFC和ATL宏大有不同.是吧,事實(shí)上它們實(shí)現(xiàn)的手法也是大不相同的.
二、MFC、ATL COM支持原理概述
首先我們必須清楚:MFC、ATL支持COM的手法是不一樣的.
MFC是通過嵌套類,而ATL是通過多繼承.
MFC支持手法概述:在一般的嵌套類解決方案中,嵌套類對象中需要維護(hù)一個(gè)指向
包裹類對象的指針,這樣才能在接口(其實(shí)是嵌套類對象)之間轉(zhuǎn)移,并實(shí)現(xiàn)與包裹類
的本身的通信.然而由于Programmers并不需要自己處理在QueryInterface時(shí)保證
接口指針指向正確的地址.事實(shí)上,ATL手法也不需要.所以MFC在具體實(shí)現(xiàn)上,
采用了MS的慣用手法:建偏移量表.表中記錄IID和接口vtable與包裹類對象地
址this之間的偏移量.這樣,在得到組件類的地址時(shí),就可以得到接口的地址,從而
調(diào)用方法.自然,這里還有一個(gè)你感覺不到的問題:不采取特殊的手段
在接口指針級回到包裹類會(huì)又是一問題,然而MFC在這個(gè)問題上的解決方案是:
早就將嵌套類的AddRef、Release、QueryInterface,轉(zhuǎn)移到包裹類的調(diào)用.
這樣還怕進(jìn)去了回不來嗎 ? 這是在xDispatch中實(shí)現(xiàn)的.
沒辦法MS就鐘情與data-driven,而且它產(chǎn)品中,這種手法的確玩的爐火純青.
我實(shí)驗(yàn)了通過在嵌套類中維護(hù)包裹類指針,事實(shí)上的確比這里的
方法不好控制.
這里的一切手段的由來,都是針對解決類嵌套的特征的.
值得講一下的是,這里使用的手法有組件的聚合之風(fēng)范.你就帶著這份感覺來
透徹的理解聚合和這里對嵌套的處理吧…
ATL支持手法概述:ATL的支持手法,可能很貼近你的思維.組件類從任意的接口繼承,
這樣就可以利用接口在C++中的虛特征實(shí)現(xiàn)方法,自然同于MFC,接口必須共享
一套AddRef、Release、QueryInterface實(shí)現(xiàn).這也是由C++的虛機(jī)制保證的.