<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文不打算嚴格地、用標準術語來講前因後果。本文主要分析實踐中常見的、因為對原理不清楚而搞出來的產品裡的坑。
外掛,Plug-In,或者(IE/Edge稱之為)載入項/Add-On,(Office稱之為)外接程式/Add-In,(GIMP稱之為)擴充套件/Extension,等等,總之看字面意思都是“額外增加功能”的這種東西,是一類開發模式。基本思路就是,研發軟體本體的時候,外部需求不明確、直到使用期仍然經常會增加功能細節。為了把變動部分切割開,在設計的時候,通過對可變部分的歸納分析,對可變部分抽象出一套介面;每套外部需求用動態庫之類的形式實現介面;軟體本體按某種約定,載入動態庫,並從中獲取外掛範例,通過介面來呼叫滿足當時需求的功能實現。
可以看到,外掛的思想,其實就是靈活運用“動態庫”的動態載入能力,把對“介面”的實現移到軟體本體之外,並用工廠模式來約束動態庫的實現方式。
只要是具有動態載入能力的執行環境上,都可以使用外掛模式來設計軟體系統。極端一些的軟體系統,甚至只提供基礎平臺,所有功能都由外掛的方式提供,例如 Visual Studio Code 、 Eclipse 等。
用C++實現外掛模式,一般是把下面這些功能組合起來:
不幸的是,由於各作業系統的動態庫機制普遍是C風格的,用C++做動態庫時候的坑,在用C++實現外掛模式時,全都會遇到。比如:
malloc
、 free
等C函數的效果,建立了__crtheap
(2010及之前版本行為)或直接使用程序預設堆(2015及之後版本行為)[1]。這導致,即使是同一個編譯器,靜態連結VC執行時會採用本模組內部的堆來實現 malloc
等,而動態連結VC執行時則會採用MSVCRT動態庫DLL的模組堆。需要解決好“誰申請誰釋放”的問題,否則記憶體管理的地方容易出異常。這裡說的不良實現,使用時候未必會錯或崩,但早晚要崩,或者會限制住外掛的開發。以下用如下外掛介面作為例子。
// IFilter.h /// 濾波器介面. class IFilter { protected: IFilter(); public: virtual ~IFilter(); public: /// 一個將輸入複數陣列處理為輸出複數陣列的函數. virtual void Filter(const std::complex<double>* acdIn, std::complex<double>* acdOut, size_t uLen) = 0; /// 獲取當前實現的一些描述字串. virtual std::string GetDescription() const = 0; }; // IFilter.cpp IFilter::IFilter() { } IFilter::~IFilter() { }
並約定外掛實現中以如下形式提供工廠函數。
// FilterPluginDll.h #include "IFilter.h" /* 外掛DLL應該提供如下函數 extern "C" int GetFilterPluginInDll(char* szFilterNamesBuf, size_t uBufLen); extern "C" IFilter* BuildFilterPlugin(const char* szFilterName); extern "C" void FreeFilterPlugin(IFilter* pFilter); */ typedef int (*PFNGetFilterPluginInDll)(char* szFilterNamesBuf, size_t uBufLen); typedef IFilter* (*PFNBuildFilterPlugin)(const char* szFilterName); typedef void (*PFNFreeFilterPlugin)(IFilter* pFilter);
比如,對外掛只發布兩個標頭檔案;認為 IFilter
的構造和解構反正是空函數無所謂,直接寫在類定義裡。
這樣,外掛開發者自己生成外掛DLL時,會在自己的DLL裡連結進一份 IFilter::IFilter()
和 IFilter::~IFilter()
的實現,而軟體本體裡也有一份自己的實現。雖然看上去,如果編譯器一樣,兩份實現是等同的,但考慮到它們使用了不同的模組堆,以及其它各種原因,外掛DLL中的 IFilter
和軟體本體裡的 IFilter
並不是完全等同的。
這裡應該由軟體本體匯出 IFilter::IFitler()
和 IFilter::~IFilter()
等介面類的共性成分的實現給外掛,以免出現一些奇怪的問題。
比如,為了“簡單”,只要求了 BuildFilterPlugin
工廠函數,認為可以由軟體本體用 delete pFilter;
來釋放外掛範例。
用類似於Windows的COM風格的“放了一堆函數指標的結構體”來表示外掛的介面定義;軟體本體裡為了使用方便,再用介面類包裝一下。
到此這篇關於使用C++實現外掛模式時的避坑要點的文章就介紹到這了,更多相關c++外掛模式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45