模板库 class 的静态成员未导出到共享库

Static member of template base class doesn't get exported to shared library

我有一个 class 'ModelManager' 是从模板 class 'TModelManager' 派生的。他们的声明如下:

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"。

在 "shared" 库中,DLLNETWORK 等同于 linux 系统上的“__attribute__((visibility("default")))”,用于导出 class。模板 class 的成员定义如下(在 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"-库中,DLLNETWORK 是一个空定义,以确保导入class。 "server"-库链接到"shared"-库。

编译正常。

在运行时,动态加载了"server"-library,这也会导致加载"shared"-library。但是,这会导致以下错误:

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

我已经在 "server"-library 上使用了 "ldd" 实用程序,确认它链接到 "shared"-library,并且可以找到它。

然后我使用 "nm" 实用程序查找与 TModelManager-class 相关的所有符号。这是结果:

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"-成员被发现两次,地址不同。

这个我真的很不明白,'m_marked'-member和'm_models'-member的定义是一样的,为什么不导出呢?为什么 'm_models' 成员出现了两次?

// 编辑:

我没有注意到 'm_models' 的纳米结果前面的 'U',这意味着它们未定义。

我定义的有问题吗?

The members of the template class are defined as such (in a cpp-file):

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

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

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