隐式使用静态库中的符号

Implicit use of symbol from a static library

我来提交我在尝试隐式从静态库中导入符号时遇到的问题。

让我用简单的代码来解决问题:

我有 3 个项目: - 定义注册表 class 的静态插件处理程序项目,它链接在其他两个项目中 - 静态插件项目 - 具有插件处理程序和 "load statically" 插件的最终项目。

首先,静态插件处理程序项目:

struct PluginType
{
    virtual void doMyStuff() = 0 ;
};

typedef PluginType* (*PluginCreator)();

struct Registry
{
      std::map<std::string, PluginCreator> _item_list;
      static Registry& instance()
      {
            static Registry singleton;
            return singleton;
      }
      static PluginType* create(std::string const& name)
      {
      // call the creator function that returns an PluginType*
        return instance()[name]();
      }
};

struct RecordInRegistry
{
     RecordInRegistry(std::string const& key, PluginCreator new_item_creator)
     {
          Registry::instance()._item_list[key] = new_item_creator;
     }
};

现在,静态插件项目

struct ADerivedItem : public PluginType
{
    virtual void doMyStuff() override
    {
        //some really interesting stuffs
    }
    static PluginType* create() { return new ADerivedItem() ; }
}


export "C" const RecordInRegistry i_record_derived_item_class("derived_item", &ADerivedItem::create);

然后,我使用插件的最终项目。该项目链接了其他两个项目!

int main()
{
    PluginType*  my_instance = Registry::create("derived_item");

    return 0;
}

我希望我能够通过链接静态库插件来注册我的静态插件 到项目。

几乎成功了!我遇到的唯一问题是静态符号 "i_record_derived_item_class" 插件没有在最终项目中明确使用,因此这个符号不是从静态插件库中导入的!

我在 visual studio 上工作,我发现了一个简单的修复方法,它包括强制导入符号,比如 /INCLUDE:i_record_derived_item_class,一切正常。

我想知道你是否看到了解决这个问题的方法,我想要的是能够添加这种静态 只需链接即可插入,无需添加任何内容 /LINK:myStaticPlugin.lib

有什么想法吗?

此外,避免特定于 MSVC 的解决方案会非常好。

提前致谢!

问题在于库中的符号仅在需要时使用。草案 n4659 在 5.2 翻译阶段说 [lex.phases]:

  1. All external entity references are resolved. Library components are linked to satisfy external references to entities not defined in the current translation.

由于您当前的源代码没有对 i_record_derived_item_class 的外部引用,也没有对 class ADerivedItem 的外部引用,因此默认情况下不会从插件项目中加载任何内容。更糟糕的是,即使是插件处理程序模块也没有引用,因此您需要声明对构建系统本身的未定义引用,无论是 MSVC 还是其他任何东西。

或者,您可以 link 包含对 i_record_derived_item_class 的外部引用的最小翻译单元(表示 .cpp 或 .o 文件),以强制从库中解析。