【问题标题】:How to instantiate static class in dynamically loaded library如何在动态加载的库中实例化静态类
【发布时间】: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 中打印或以其他方式转储 &amp;ModuleFactory::Instance() - 我怀疑您会看到两个不同的地址。
  • 不幸的是,不是这样。我将ModuleFactory 移动到一个.dll 中,专门通过静态链接阻止这种情况发生。 DefaultPlugin 的构造函数永远不会被调用。
  • 上面的红鲱鱼位,DefaultPlugin 的构造函数不应该在注册期间被调用:-D 注册也没有发生,但我认为我应该清除它。我看到一个测试插件注册自己,如果它位于 .dll 项目本身的标头中,而不是它链接的库之一。

标签: c++ dynamic dll plugins shared


【解决方案1】:

OK:超级掌心时间。 我一直在将我的代码结构重新组织成如此好的分离库,以至于我实际上并没有在 dll 代码的任何地方包含包含我的静态插件声明的标头!

不过,我会留下这个问题,因为我发现这是一个非常不寻常的配置,它可能会帮助某人知道它可以工作。

请注意,在 MS 运行时中,静态在 initterm.cpp 中的 _initterm 中初始化,来自 dll_main_crt_process_attach,这也可能会有所帮助。

【讨论】:

    猜你喜欢
    • 2018-06-15
    • 2016-02-26
    • 1970-01-01
    • 2011-08-20
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    相关资源
    最近更新 更多