6

我在 win7 中使用 VS2008,在 CentOS 18 中使用 g++ 4.7。仅当我使用动态共享库时,才会在 Windows 上看到此问题。当我将其转换为静态库时,程序链接正常。

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

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

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

但是我无法弄清楚为什么在将库转换为 dll 后在 Windows 中它无法解析符号:错误 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

//库.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;
}
4

3 回答 3

4

我相信您需要导出专业。您是否在 .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

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

于 2013-07-08T06:44:04.377 回答
3

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

于 2013-07-08T12:56:01.457 回答
0

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

于 2014-03-21T18:01:15.760 回答