OK, so I read a few questions and articles on this topic, and it seems to me that I understand the basics, but I still have problems.
I have a DLL that exports a class with std :: string as a member. My main program contains classes that also have strings, and uses a DLL.
If I compile a DLL in VS2010, I get the following warnings:
warning C4251: 'MyClass::data' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'MyClass'
When I compile the EXE, I get the same warnings, but there are no errors, and the program compiles and runs. This is actually a big project, so I get as many as 40 warnings, and I'm not too keen on it. (As a side observation, these warnings are missing when compiling with VS2008)
So, I read about this warning, and it led me to this MS article: http://support.microsoft.com/default.aspx?scid=KB;EN-US;168958 which tells how to export the STL template from a DLL, to satisfy the warnings I received.
The problem is that to remove the warnings I add the following lines:
EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator<char>; EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string< char, std::char_traits<char>, std::allocator<char> >;
compiling a DLL without warning, but when I compile my EXE, the linker throws a fit:
2>SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in OtherClass.obj 2>SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: unsigned int __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::size(void)const " (?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ) already defined in OtherClass.obj
Both DLL and EXE are compiled with the same code generation options. I can use MT on both or MD, and the results are the same.
I am including code from a minimized example program in case I left anything above.
My main question is: can I fix the LNK2005 errors or can I just ignore the warnings C4251?
Edit: So, I read a little more, and it looks like std :: string, which uses the DLL class, is a private variable that only member functions are accessible to, it can be safely ignore the warning ... Any comments on this? Is this a step in the right direction?
Dll code:
#pragma once #include <exception> #include <string> #ifdef SAMPLEDLL_EXPORTS # define DECLSPECIFIER __declspec(dllexport) # define EXPIMP_TEMPLATE #else # define DECLSPECIFIER __declspec(dllimport) # define EXPIMP_TEMPLATE extern #endif //disable warnings on extern before template instantiation (per MS KB article) #pragma warning (disable : 4231) //std::basic_string depends on this allocator, so it must also be exported. EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator<char>; //std::string is a typedef, so you cannot export it. You must export std::basic_string EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string< char, std::char_traits<char>, std::allocator<char> >; #pragma warning (default : 4231) class DECLSPECIFIER MyClass { public: std::string getData(); //returns 'data', body in CPP file private: std::string data; int data2; }; //in SampleDLL.cpp file... std::string MyClass::getData() { return data; }
EXE code:
#include <iostream> #include "SampleDLL.h" using namespace std; void main() { MyClass class1; cout << class1.getData() << endl; }