【问题标题】:Static member of template base class doesn't get exported to shared library模板基类的静态成员不会导出到共享库
【发布时间】:2015-05-09 02:40:31
【问题描述】:

我有一个从模板类“TModelManager”派生的“ModelManager”类。他们的声明如下:

template<class TModel,class TModelMesh,class TModelSubMesh>
    class TModelManager
{
protected:
    static std::map<std::string,ModelHandle> m_models;
    static std::vector<std::map<std::string,ModelHandle>::iterator> m_marked;
    [...]
};

class DLLNETWORK ModelManager
    : public TModelManager<Model,ModelMesh,ModelSubMesh>
{
    [...]
};

有两个共享库,“shared”和“server”。

在“共享”库中,DLLNETWORK 相当于 linux 系统上的 '__attribute__((visibility("default")))',用于导出类。模板类的成员是这样定义的(在 cpp 文件中):

template<class TModel,class TModelMesh,class TModelSubMesh>
    DLLNETWORK std::map<std::string,ModelHandle> TModelManager<TModel,TModelMesh,TModelSubMesh>::m_models;
template<class TModel,class TModelMesh,class TModelSubMesh>
    DLLNETWORK std::vector<std::map<std::string,ModelHandle>::iterator> TModelManager<TModel,TModelMesh,TModelSubMesh>::m_marked;

在“server”-library 中,DLLNETWORK 是一个空定义,以确保类被导入。 “服务器”库与“共享”库链接。

这样编译就好了。

在运行时,“服务器”库被动态加载,这也会导致“共享”库被加载。但是,这会导致以下错误:

Unable to load library 'lib/libserver_x64.so': lib/libserver_x64.so: undefined symbol: _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_markedE

我在“服务器”库上使用了“ldd”实用程序,它确认它与“共享”库链接,并且可以找到它。

然后,我使用“nm”实用程序查找与 TModelManager 类相关的所有符号。结果如下:

nm -D libshared_x64.so | grep ModelManager
0000000000b15610 u _ZGVN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_modelsE
000000000072d1b0 T _ZN12ModelManager21CreateFromBrushMeshesERSt6vectorIP9BrushMeshSaIS2_EE
000000000072d10c T _ZN12ModelManager4LoadESs
000000000072d950 W _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE21CreateFromBrushMeshesERSt6vectorIP9BrushMeshSaIS6_EE
000000000072d62c W _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE4LoadESsPFP8MaterialPKcE
0000000000b155e0 u _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_modelsE

一切都在那里,除了“m_marked”成员。 “m_models”-member 被发现两次,但地址不同。

我真的完全不明白,'m_marked'-member 的定义方式和'm_models'-member 一样,那为什么不导出呢?为什么“m_models”成员会出现两次?

// 编辑:

我没有注意到“m_models”的 nm 结果前面的“U”,这意味着它们未定义。

我对它们的定义有问题吗?

【问题讨论】:

    标签: c++ shared-libraries ubuntu-14.04 nm template-classes


    【解决方案1】:

    模板类的成员是这样定义的(在 cpp 文件中):

    您似乎假设这些定义将在 cpp 文件中实例化,但除非该 cpp 文件中的某些内容使用它们,否则成员将 被实例化,因此相应的符号将不会被实例化在编译的目标文件中发出。

    服务器库中使用这些静态成员的代码无法隐式实例化它们,因为您已将定义隐藏在 cpp 文件中。

    静态成员定义要么需要为您正在使用的所有特化显式实例化,要么您需要将这些定义放在标题中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多