不同dll中的C ++模板专业化会产生链接器错误

约瑟夫

我有一个第三方dll,其中包含具有多个专业化的模板类。我在Linux上有自己的专长,尝试编译Windows dll,但是会导致链接器错误。

我尝试了一下,发现模板头上的dllimport规范可能是原因,删除它可以解决我的问题。但是,我不想修改或复制标头,因为它可能会随着对第三方库的每次更新而中断。

这是重现我的问题的最小示例

test.h-dll / so标头:

#ifdef _WIN32
#ifdef EXPORT
#    define LIB_EXPORT __declspec(dllexport)
#else
#    define LIB_EXPORT __declspec(dllimport)
#endif
#else
#    define LIB_EXPORT
#endif

template <typename A> class LIB_EXPORT Foobar
{
   public:
      virtual void helloWorld(){}
      virtual ~Foobar(){}
}; 

test.cpp-dll /如此实现:

#define EXPORT
#include "test.h" 

template class __declspec(dllexport) Foobar<int>;

main.cpp-示例程序:

#include "test.h"
//explicit instanciation - does not help
template class __declspec(dllexport) Foobar<char>;
int main(int argc, char** argv)
{
    Foobar<char> a;
    a.helloWorld();
}

有一种干净的方法可以在我的可执行文件中完整地实例化Foobar吗?

使用的编译器:Visual Studio 2010,g ++ mingw w64 4.9.1

Ben

我知道您说过您不想修改标头,因为它可能破坏第三方库的更新,但是定义模板的标头设置不正确。希望您可以让您的供应商修改其标头,使其对导入/导出更加友好。

目标:

在dll / so中定义(导出)模板专业化,然后对您的exe使用(导入)该专业化。

测试


我们希望只导入或导出每个模板的专业化,所以我们从类中删除的LIB_EXPORT。

template <typename A> class Foobar {
...
}

我们确实想导入/导出模板的特定专业化。我们将向前声明特殊化,然后稍后在您希望其驻留的编译单元中显式实例化它。

由于您还使用gcc进行构建,因此您将需要使用'extern'关键字。Visual Studio 2010不会为模板实现它。

#ifdef _WIN32
#    define TEMPLATE_EXTERN
#ifdef EXPORT
#    define LIB_EXPORT __declspec(dllexport)
#else
#    define LIB_EXPORT __declspec(dllimport)
#endif
#else
#    define TEMPLATE_EXTERN extern
#    define LIB_EXPORT
#endif

最终的前向声明看起来像

TEMPLATE_EXTERN template class LIB_EXPORT Foobar<int>;

测试文件


由于在头文件中的工作已关闭了编译器的自动实例化功能,因此我们在此处显式实例化了模板类。

#define EXPORT
#include "test.h" 

template class Foobar<int>;

main.cpp


标头的默认状态是使用任何非int类型隐式实例化Foobar类。int专业化已在gcc上标记为'export',在win32上被标记为__declspec(dllimport)。因此,您可以随时随地进行其他专业化研究。

#include "test.h"

// explicit instantiation
template class Foobar<char>;

int main(int argc, char** argv)
{
    Foobar<char> a;
    a.helloWorld();
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章