类和函数模板实例化的Visual Studio dll导出问题



我在win7中使用VS2008,在centos18中使用g++4.7。只有当我使用动态共享库时,才会在Windows上看到这个问题。当我转换它的静态库程序链接良好。

我知道在共享库中,模板函数/类要么应该在头文件中定义,要么应该通过编译单元提供模板类型(参数)的模板实例化。我选择了以后的选项。我以前做过,我通过了

为什么模板只能在头文件中实现?

带有模板的C++共享库:未定义的符号错误

但我不明白为什么在windows中,当我将库转换为dll时,它无法解析符号:错误LNK2019:未解析的外部符号"void __cdecl HelpingRegistration(double)"(?)$HelpingRegistration@N@@YAXN@Z)在函数_main 中引用

在Windows中,它可以很好地与静态库配合使用。在Linux中,动态库和共享库都可以工作。

//Static library
//Library header
#ifndef _TEMPLATED_STATIC_LIB_
#define _TEMPLATED_STATIC_LIB_
#include <iostream>
#include <string>
#include "Export.h"
template<typename T>
class EXPORT TemplatedStaticLib
{
public:
    TemplatedStaticLib(){};
    ~TemplatedStaticLib(){};
    void print(T t);
};
template<typename T>
EXPORT void HelpingRegistration(T);
#endif

//library.cpp

#include "TemplatedStaticLib.h"
#include <typeinfo>

template<typename T>
void TemplatedStaticLib<T>::print(T t)
{
    std::cout << "Templated Print: "<< t<< " type:: "  << typeid(t).name() << std::endl;
}
//Class Template explicit instantiation
template class TemplatedStaticLib<double>;
template class TemplatedStaticLib<std::string>;
template<typename T>
void  HelpingRegistration(T t)
{
    std::cout << "Function Templated Print: "  << t << " type: " << typeid(t).name() << std::endl;
       //return t;
}
//function template explicit instantiation
template void HelpingRegistration<>( double );
template void HelpingRegistration<>( std::string );

//Windows符号导出程序

//.h
#ifndef STATIC_LIB_EXPORT
#define STATIC_LIB_EXPORT
#if !defined WIN32
    #define EXPORT
#elif defined LIB_EXPORTS
    #define EXPORT __declspec(dllexport)
#else
    #define EXPORT __declspec(dllimport)
#endif
//STATIC_LIB_EXPORT
#endif

//库用户.cpp

#include <TemplatedStaticLib/TemplatedStaticLib.h>
#include<string>
int main(int argc, char* argv[])
{
    double aDouble = 3.9;
    TemplatedStaticLib<double> double_test; 
    double_test.print(aDouble);
    std::string aString = "James";
    TemplatedStaticLib<std::string> string_test; 
    string_test.print(aString);
    HelpingRegistration(aDouble);
    HelpingRegistration(aString);

    return 0;
}

我认为您需要导出专业化。你在.cpp文件中尝试过吗:

template class EXPORT TemplatedStaticLib<double>;
template class EXPORT TemplatedStaticLib<std::string>;

在你的标题中几乎相同:

template class EXPORT TemplateStaticLib<double>;
template class EXPORT TemplateStaticLib<std::string>;

认为将适用于EXPORT宏(假设.cpp文件见__declspec(dllexport),标头见__declspec(dllimport))。我承认我不是Windows的__declspec专家。

我承认我的答案是从网上的另一个答案中得出的:http://social.msdn.microsoft.com/Forums/vstudio/en-US/4fd49664-e28e-4f23-b1eb-b669d35ad264/function-template-instantation-export-from-dll(一直滚动到Franjo555最终版本的底部。)

我解决了这个问题。在windows下,类模板和函数模板的导出方式不同,网上有一篇有趣的文章。

如果类模板在翻译单元(.cpp)上实例化,VS编译器将导出类模板符号。

但是,在函数模板的情况下,需要显式显示关键字"__declspec(dllexport)",以便在动态库中显示符号。

例如

template EXPORT void HelpingRegistration<double>( double );
//EXPORT is defined as __declspec(dllexport) 

这只是VS以不同方式决定事情的另一种情况。这里有有趣的阅读:http://www.codesynthesis.com/~boris/blog/2010/01/18/dll导出cxx模板/

我相信这是因为当模板类首次与特定参数一起使用时,编译器会为模板类创建专门的代码。由于编译器在编译编译单元(.cpp文件)时只使用包含的头文件(.h),因此所有的tmplate代码都必须在.h文件中可用。您可以从dll导出专用模板类,但不能导出模板类本身。

最新更新