(由作者重新陳述以使其更清楚)。編譯時插件/具有單獨模塊約束的自動工廠註冊
是的,另一個自動化工廠註冊問題。但是我有新的(可能太有雄心的)限制。我爲一個大型(人類大腦)項目工作,需要使圖像I/O模塊可擴展。這是我想要實現的管道:
- 開發人員根據一個簡單的基於工廠的API編寫自己的圖像I/O插件。
- 他/她不允許修改我的代碼。
- 他/她將源文件放入我爲此創建的插件文件夾中。
- 他/她啓動cmake並編譯整個項目。 CMake會自動發現新文件並將其包含在項目中。
- 前
main()
時間,新的插件類被發現並自動註冊到工廠。 在
main()
,我可以做Base* b = Factory::create("DerivedClass"); b->dosomething();
這裏是我的建議,其中混合以前的工作和建議,在網絡上找到。但是,這是行不通的,除非插件的頭被包含在main.cpp
,它打破了要求2
ImageFormat.h
class Format
{
public:
virtual std::string id() const = 0;
virtual void dosomething() = 0;
virtual ~Format() {}
};
typedef Format* (*PluginCreator)(void);
class FormatFactory
{
private:
std::map<std::string, PluginCreator> registry; //map of registered plugins
public:
static FormatFactory* instance()
{
static FormatFactory* uniqueInstance = new FormatFactory();
return uniqueInstance;
}
static std::string registerPlugin(PluginCreator creator, std::string id)
{
instance()->creators[id] = creator;
return id;
}
static Format* create(std::string id) throw (myexception)
{
if(instance()->creators.find(id) == instance()->creators.end())
throw myexception("Format not found");
return (instance()->creators[id])();
}
};
ExampleFormat.h
class ExampleFormat : public Format
{
private:
static const std::string id;
static Format* create() { return instance(); }
public:
static ExampleFormat* instance(){
static ExampleFormat* uniqueInstance = new ExampleFormat();
return uniqueInstance;
}
std::string id() const { return id; }
void dosomething(){"I am an example format and I do pretty cool stuff";}
};
// this should guarantee that the singleton is instantiated. But works only if this header is included in the main.cpp or other modules of the main project.
namespace{
static const ExampleFormat* object = ExampleFormat::instance();
}
ExampleFormat.cpp
#include "ExampleFormat.h"
const std::string ExampleFormat::id = FormatFactory::registerPlugin(&create, "ExampleFormat");
main.cpp
#include "ImageFormat.h"
int main()
{
FormatFactory::create("ExampleFormat")->dosomething();
return 1;
}
謝謝 亞歷山德羅
你想使你的插件動態庫?那麼當你加載這個庫的時候,這些單例變得可用(可以通過將插件發現者作爲一個將所有動態庫加載到插件目錄中的單例來做到這一點) – BeyelerStudios 2014-09-03 09:40:56
@BeyelerStudios:是的,我們已經討論過它,此時此刻。跨平臺可移植性是主要要求,我們希望儘可能使這個項目儘可能便攜。 DLL插件是一件好事(我開發了很多),但可移植性是一個問題。 – alessandro 2014-09-03 09:46:24
你可能可以做的就是讓CMake創建一個包含所有發現插件的頭文件。在你的main.cpp中包含這個頭文件,你應該是金手指。 – BeyelerStudios 2014-09-03 09:59:34