jaz*_*man 5 c++ templates shared-libraries
我在win7中使用VS2008,在CentOS 18中使用g ++ 4.7.只有在我使用动态共享库时才能在Windows上看到这个问题.当我转换它静态库时程序链接正常.
据我所知,在共享库模板函数/类中应该在头文件或模板中定义模板类型(参数)的实例化应该通过编译单元提供.我选择了后一个选项.我以前做过,我经历过
但我无法弄清楚为什么在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
Run Code Online (Sandbox Code Playgroud)
//库.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 );
Run Code Online (Sandbox Code Playgroud)
// 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
Run Code Online (Sandbox Code Playgroud)
//库用户.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;
}
Run Code Online (Sandbox Code Playgroud)
我解决了这个问题。在Windows下,类模板和函数模板的导出方式不同,网上有一篇有趣的文章。
如果类模板在翻译单元 (.cpp) 上实例化,则 VS 编译器会导出类模板符号。
但是,在函数模板的情况下,需要显式存在关键字“__declspec(dllexport)”,以便符号出现在动态库上。
例如
template EXPORT void HelpingRegistration<double>( double );
//EXPORT is defined as __declspec(dllexport)
Run Code Online (Sandbox Code Playgroud)
这只是 VS 做出不同决定的另一个例子。这里有有趣的阅读: http://www.codesynthesis.com/~boris/blog/2010/01/18/dll-export-cxx-templates/