我在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导出专用模板类,但不能导出模板类本身。