總結(jié)下C++中模塊(Dll)對外暴露接口的方式:
(1)導(dǎo)出API函數(shù)的方式這種方式是Windows中調(diào)用DLL接口的最基本方式,GDI32.dll, User32.dll都是用這種方式對外暴露系統(tǒng)API的。
這種方式的優(yōu)點是導(dǎo)出函數(shù)沒有語言限制,什么語言都能調(diào)用;
缺點是這種方式是面向過程的,外部如果要支持多實例等不是很方便,另外它要求的回調(diào)函數(shù)(callback)只能是普通C函數(shù),C++中我們通常用類靜態(tài)成員函數(shù),很不方便。
當(dāng)然,我們通過封裝其實也可以讓這種方式支持多實例,通過一個抽象句柄HComponent, 比如支持導(dǎo)出函數(shù)HComponent CreateInstance(); VOID DeleteInstance(HComponent h);然后內(nèi)部的其他導(dǎo)出函數(shù)的第一個參數(shù)都是實例句柄,類似INT SendMessage(HComponent h, ...), 用這種方式可以模擬出面向?qū)ο蟮男Ч?br />另外如果用動態(tài)加載(LoadLibrary, GetProcAddress)的方式調(diào)用它的導(dǎo)出函數(shù),即使導(dǎo)出函數(shù)內(nèi)部實現(xiàn)修改了,外部程序也不用重新編譯,仍然可用。
導(dǎo)出函數(shù)方式一個比較優(yōu)秀的例子是GDI+的實現(xiàn),整個GdiPlus.dll對外提供的都是普通導(dǎo)出函數(shù),但是它卻可以方便的給面向?qū)ο蟮恼Z言使用,因為一方面它用Handle的方式在DLL內(nèi)部封裝了對象,另一方面它在DLL外圍又用C++類的方式封裝了頭文件直接提供給用戶, 所以C++程序可以直接以面向?qū)ο蟮姆绞秸{(diào)用。
(2)導(dǎo)出類方式導(dǎo)出類的方式就是把整個C++類對外導(dǎo)出, MFC42.dll就是這種方式。
這種方式的優(yōu)點是直接面向?qū)ο蟆?br />缺點是只能給C++用,而且最好編譯器都要一致,另外DLL一變動, 外部程序需要重新編譯, 而且外部程序可以通過頭文件看到你類的內(nèi)部實現(xiàn),
所以這種方式是最不建議使用的方式。
(3)COM方式
COM方式實際上導(dǎo)出了幾個固定函數(shù)(DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer), 然后以這幾個函數(shù)為入口,調(diào)用組件內(nèi)部‘實現(xiàn)的接口。
COM方式綜合了上面2種方法的所有優(yōu)點,沒有語言限制,面向?qū)ο螅鄬嵗荒芸吹浇涌冢瑒討B(tài)升級等。
當(dāng)然COM因為其復(fù)雜性和對注冊表的依賴,很多時候我們在封裝模塊時不愿意嚴格按照COM標準來實現(xiàn),但是我們可以按照COM思想來提供接口。
比如我們可以讓我們模塊只提供一個導(dǎo)出函數(shù)CreateFactory, 然后外部可以調(diào)用該接口來創(chuàng)建工廠,最后通過工廠創(chuàng)建出各種類型的對象,這些對象實現(xiàn)了某些接口,外部只需要這些接口的頭文件即可調(diào)用對象的方法。
現(xiàn)在越來越多的組件以這種方式對外提供接口,比如D2D對外的導(dǎo)出接口就是
D2D1CreateFactory, 然后就可以通過該工廠來創(chuàng)建其他的對象,比如pD2DFactory->CreateHwndRenderTarget(...),最后可以直接調(diào)用對象實現(xiàn)的接口:pRenderTarget->DrawRectangle(D2D1::RectF(100.f, 100.f, 500.f, 500.f), pBlackBrush);
當(dāng)然,上面幾種DLL對外暴露接口的方式本質(zhì)上沒有區(qū)別,都是利用PE文件的導(dǎo)出節(jié)來導(dǎo)出數(shù)據(jù)和函數(shù),但是根據(jù)它們使用方式的不同,對外部模塊來說還是有很大的區(qū)別,我們的推薦次序依次是:COM方式->導(dǎo)出API函數(shù)方式->導(dǎo)出類方式。
posted on 2012-08-29 18:58
Richard Wei 閱讀(4295)
評論(0) 編輯 收藏 引用 所屬分類:
C++