【发布时间】:2021-09-06 17:55:15
【问题描述】:
我正在使用一个基于工厂的编译时插件系统,我希望它变得更加动态。 目前它基于静态模板化注册器类,其中构造函数将类注册到工厂。 例如
template <class T>
SingleModuleRegistrar<T>::SingleModuleRegistrar(ModuleDesc description={ T::factoryName(), T::category }) : _name(description.moduleName)
{
ModuleFactory& factory = ModuleFactory::Instance();
factory.Register(this, description);
}
然后在 DefaultPlugin 类的标题中
static SingleModuleRegistrar<DefaultPlugin> DefaultPluginRegistrar;
当这是在静态库中构建时,DefaultPlugin 在工厂注册并可供使用。
现在我想将静态库移动到一个 dll 中,这样我就可以动态地将新插件添加到工厂中。
我可以加载 dll 没问题,但静态变量似乎没有得到 instatiated。你会期待吗,如果没有,我怎样才能触发静态DefaultPluginRegistrar 的实例化?
我可以想到一些解决方法,例如添加一个函数来在库中注册插件并调用它,但我想如果我可以让事情尽可能接近原始代码,那就太好了。 另外,我想了解加载过程中静态变量实例化的情况。
编辑:
我想我应该添加一些关于结构的更多细节。目前,DefaultPlugin 注册位于静态链接到 .dll 的库中的标头中。它也在命名空间中。
MyPlugin.dll
|_ MyStaticLibrary.lib
|_DefaultPlugin.h
SomeNamespace {
class DefaultPlugin : public IPlugin
{
public:
DefaultPlugin();
//etc.
};
// registration
static SingleModuleRegistrar<DefaultPlugin> DefaultPluginRegistrar;
}
|_ SomeOtherStaticLibrary.lib
我也试过删除静态声明并导出符号,但无济于事
__declspec(dllexport) SingleModuleRegistrar<DefaultPlugin> DefaultPluginRegistrar;
【问题讨论】:
-
您使用的是什么编译器/工具集? IIRC,DLL 中的运行时支持应该处理全局变量的初始化(我认为是在 DLL_PROCESS_ATTACH 消息上)。
-
我目前正在使用 Visual Studio,但也需要能够在 Linux/gcc 上执行此操作
-
我的猜测是,DLL 获得了自己的
ModuleFactory“singleton”副本并在其中注册 - 而不是 EXE 所查看的副本。在 EXE 和 DLL 中打印或以其他方式转储&ModuleFactory::Instance()- 我怀疑您会看到两个不同的地址。 -
不幸的是,不是这样。我将
ModuleFactory移动到一个.dll 中,专门通过静态链接阻止这种情况发生。DefaultPlugin的构造函数永远不会被调用。 -
上面的红鲱鱼位,
DefaultPlugin的构造函数不应该在注册期间被调用:-D 注册也没有发生,但我认为我应该清除它。我看到一个测试插件将注册自己,如果它位于 .dll 项目本身的标头中,而不是它链接的库之一。
标签: c++ dynamic dll plugins shared