Visual Studio dll导出问题类和函数模板实例化 [英] Visual Studio dll export issue for class and function template instantiations

查看:862
本文介绍了Visual Studio dll导出问题类和函数模板实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用VS2008在win7和g ++ 4.7在CentOS 18.这个问题只有在Windows上使用动态共享库时才会出现。当我转换它静态库的程序链接罚款。



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



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



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



但我无法弄清楚为什么在Windows中,只要我将库转换为dll,它无法解析符号:
error LNK2019:unresolved外部符号void __cdecl HelpingRegistration(double)在函数_main中引用的$ @ HelpingRegistration @ N @@ YAXN @ Z)在Windows中它可以与静态库一起工作。
在Linux中,动态和共享库工作。

  //静态库
//库标头
#ifndef _TEMPLATED_STATIC_LIB_
#define _TEMPLATED_STATIC_LIB_

#include< iostream>
#include< string>
#includeExport.h

template< typename T>
class EXPORT TemplatedStaticLib
{
public:
TemplatedStaticLib(){};
〜TemplatedStaticLib(){};

void print(T t);

};

template< typename T>
EXPORT void HelpingRegistration(T);

#endif

//库.cpp

  #includeTemplatedStaticLib.h
#include< typeinfo>


template< typename T>
void TemplatedStaticLib< T> :: print(T t)
{
std :: cout< 模板打印:< t < type ::<< typeid(t).name()< std :: endl;
}

//类模板显式实例化
模板类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;
}

//函数模板显式实例化
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);

帮助注册(aDouble);
HelpingRegistration(aString);


return 0;
}


解决方案

在Windows类下,模板和函数模板以不同的方式导出,并且在网络上有一个有趣的阅读。



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



但是,在函数模板的情况下,关键字'__declspec(dllexport)'需要显式地出现在动态库上出现的符号。



例如

 模板EXPORT void HelpingRegistration< double>(double); 
// EXPORT定义为__declspec(dllexport)

这是另一种情况,事情不同。有一个有趣的阅读:
http://www.codesynthesis.com/~boris/blog/2010/01/18/dll-export-cxx-templates/


I am using VS2008 in win7 and g++ 4.7 in CentOS 18. The issue is only seen on Windows when I used dynamically shared library. When I convert it static library the program links fine.

I understand that in shared library template functions/class either should be defined in header file or template instantiation of the template types(parameters) should be provided through compilation unit. I have chosen the later option. I have done it before, I went through

Why can templates only be implemented in the header file?

C++ Shared Library with Templates: Undefined symbols error

But I cannot figure out why in windows as soon as I convert the library to dll it failed to resolve symbols: error LNK2019: unresolved external symbol "void __cdecl HelpingRegistration(double)" (??$HelpingRegistration@N@@YAXN@Z) referenced in function _main

In Windows it works fine with static library. In Linux both dynamic and shared library works.

//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 symbol exporter

//.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

//library user .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;
}

解决方案

I worked out the problem. Under windows class template and function template are exported differently and there is a interesting reading on the net.

VS compilers exports class template symbols if class template is instantiated on the translation unit (.cpp).

However, in the case of function template, the keyword '__declspec(dllexport)' needs to be present explicitly for the symbols to be present on the dynamic library.

e.g

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

It's just another case where VS decide to things differently. There is interesting reading here: http://www.codesynthesis.com/~boris/blog/2010/01/18/dll-export-cxx-templates/

这篇关于Visual Studio dll导出问题类和函数模板实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆