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

jaz*_*man 5 c++ templates shared-libraries

我在win7中使用VS2008,在CentOS 18中使用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
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)

jaz*_*man 3

我解决了这个问题。在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/