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 believe you need to export the specializations. Have you tried this in your .cpp file:
template class EXPORT TemplatedStaticLib<double>;
template class EXPORT TemplatedStaticLib<std::string>;
and pretty much the same in your header:
template class EXPORT TemplateStaticLib<double>;
template class EXPORT TemplateStaticLib<std::string>;
I think that will work with your EXPORT macro (assuming the .cpp file see __declspec(dllexport)
and the header sees __declspec(dllimport)
). I admit I'm not an expert with Windows' __declspec
.
I admit that I drew my answer from this other answer on the intarwebs: http://social.msdn.microsoft.com/Forums/vstudio/en-US/4fd49664-e28e-4f23-b1eb-b669d35ad264/function-template-instantation-export-from-dll (scroll all the way to the bottom for Franjo555's final version.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With