C++ 通过元编程或其他方式在dll模块内自动注册静态对象工厂

C++ 通过元编程或其他方式在dll模块内自动注册静态对象工厂,c++,dll,factory-pattern,C++,Dll,Factory Pattern,在我正在进行的一个项目中,我想将类放入一个dll中,该dll将由一个抽象工厂初始化,并通过在主程序中的对象中组合而包含。其目的是允许用户创建自己的dll模块,从而添加自己的功能。dll模块本身应该尽可能简单;理想情况下,它只包含功能类及其基类。用户只能访问dll的源代码,而不能访问主程序或工厂 我在codeproject.com上找到了一些抽象工厂的代码,对我来说很不错。下面是示例代码: 代码: 实现这一点的明显方法是在每个被调用以构建映射的dll中都有一个注册函数。我的问题:是否有可能让我的程

在我正在进行的一个项目中,我想将类放入一个dll中,该dll将由一个抽象工厂初始化,并通过在主程序中的对象中组合而包含。其目的是允许用户创建自己的dll模块,从而添加自己的功能。dll模块本身应该尽可能简单;理想情况下,它只包含功能类及其基类。用户只能访问dll的源代码,而不能访问主程序或工厂

我在codeproject.com上找到了一些抽象工厂的代码,对我来说很不错。下面是示例代码:

代码:

实现这一点的明显方法是在每个被调用以构建映射的dll中都有一个注册函数。我的问题:是否有可能让我的程序以某种方式(例如通过某种元编程技术)自动在地图中注册工厂,这样用户就不需要执行此功能,因为这可能会有一个很长的地图分配列表?我想做的是在编译时创建dll类的列表或脚本,然后在运行时从列表中执行注册


非常感谢您的帮助。

我正在使用全局对象构造函数进行此类注册。与适当的C++链接器连接,动态库在模块初始化时调用这些构造函数。析构函数也很有用-您可以在那里执行注销

因此,我们的想法是使用包含所有已加载工厂的全局映射。从每个库中定义的某个全局对象的构造函数中填充它


在VisualStudio中,您可能需要强制链接器不使用构造函数优化实例对象。这可以通过导出有问题的全局变量来完成。

您可以通过要求每个DLL导出两个简单函数来轻松完成

void getAvailableComponents(std::list<string> &components);
IComponent *getComponent(const std::string &componentName);
在这里,getComponentFactory可以返回包含附加功能的类的实例,也可以返回创建附加功能的轻量级工厂。IComponent的功能、行为方式以及处理各种类类型的方式实际上取决于您以及您希望公开多少环境


请注意,要从程序中访问这些函数,您需要将它们的修饰名称传递给GetProcAddress

,这对静态gloabl构造函数是有风险的。请参阅以下链接:在C++中静态连接使用全局或静态构造函数和析构函数的程序可能是一个令人困惑的、有时很棘手的命题。最简单的答案是一个常见的建议:不要做。问题是关于动态链接,不是吗?导出的符号总是存在的,链接器不能消除它们。我们不能说太多。关于静态初始化顺序,但我们知道组件的加载时间晚于注册服务,这就是我们所需要的。顺便说一句,MS格式很难阅读。正如我所说的,即使是动态链接,也存在风险。例如,如果DLL是由LIB组成的,则需要小心不要将全局对象构造函数放在LI中Bs,因为这不会以一种简单的方式工作。你能进一步解释LIBs问题吗?为什么我们单独的、独立于其他对象的、动态导出的全局对象会有初始化困难?我不想为我的方法辩护,我只是想更好地理解这些细微差别。当链接器假设不使用编译单元中的任何代码,并忽略该编译单元中的任何全局或静态构造函数。如果导出对象,则不会发生这种情况,但导出全局对象的目的只是为了确保这一点吗?全局对象仅为其静态构造函数创建。这与指定pr非常类似agma commentlinker,/INCLUDE:…用于相同目的。至少编辑您的帖子,并提及链接器必须知道每个库中定义的此全局对象。
void getAvailableComponents(std::list<string> &components);
IComponent *getComponent(const std::string &componentName);