When exporting an STL std :: basic_string template from a DLL, I get LNK2005 error

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; } 
+8
c ++ dll stl visual-studio-2010
source share
5 answers

It looks like you are seeing the problem described in connect.microsoft.com .

There is a workaround, but that seems a bit unpleasant.

Other options that may help:

  • Do not export std :: string, use const char * instead in the dll interface (see https://stackoverflow.com/a/1656464/169 )
  • Make sure _ITERATOR_DEBUG_LEVEL matches for all of your projects
+3
source share

The link to the MS article you submitted says that some STL classes "... have already exported C Runtime DLLs, so you cannot export them from your DLL." Including basic_string. And your link error says that the basic_string symbol "... is already defined in OtherClass.obj". Because the linker sees two identical symbols in two different places.

+2
source share

When exporting an STL std :: basic_string template from a DLL, I get LNK2005 error

Also see Microsoft KB article 168958 How to export an instance of a standard template library (STL) class and a class that contains a data item that is an STL object . From the article:

Export STL Class

  • Both in the DLL and in the .exe file, the link to the same version of the DLL is version C. Either link both to Msvcrt.lib (release build) or link both to Msvcrtd.lib (debug build).
  • In the DLL, specify the __declspec qualifier in the template creation declaration to export an instance of the STL class from the DLL.
  • In the .exe file, specify the extern and __declspec qualifiers in the template creation declaration to import the class from the DLL. This leads to a warning against using the non-standard extension C4231: 'extern' before explicitly instantiating the template. "You can ignore this warning.
0
source share

I got a hack, can fix it in temp

Open the project options, click Linker-> Command Line. In the input field for additional options, enter

  /FORCE:MULTIPLE 
0
source share

The whole topic came down to me

  • Do not export STL files. Ignore warning. (At least until MSVC2013.)
  • Of course, make sure that each side references the C runtime in the same way as debug / release, static / dynamic.

Always fixed the problem for me so far.

Unfortunately, this is not an answer if you do not have control over the source code that you would like to link to.

0
source share

All Articles