3

With VS2013 and a suitable export macro, I could use this example code to export std::string and std::vector:

#ifdef _MSC_VER
// Explicit template exports.
c_EXPORT_TEMPLATE template class c_EXPORT std::allocator<char>;
c_EXPORT_TEMPLATE template struct c_EXPORT std::char_traits<char>;
c_EXPORT_TEMPLATE template class c_EXPORT std::basic_string<char, std::char_traits<char>, std::allocator<char> >;
c_EXPORT_TEMPLATE template class c_EXPORT std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >;
c_EXPORT_TEMPLATE template class c_EXPORT std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >;
#endif

(compilable testcase here: https://github.com/rleigh-dundee/dlltest)--this works both as a static library or as DLLs using

cmake -G "Visual Studio 12 2013 Win64" -DBUILD_SHARED_LIBS=ON|OFF /path/to/source

With VS2015 ("Visual Studio 14 2015 Win64") I get warnings when compiling with a DLL related to std::string:

c:\users\rleigh\libtest\a.h(30): warning C4251: 'std::_String_alloc>::_Mypair': class 'std::_Compressed_pair>,std::_String_val>,true>' needs to have dll-interface to be used by clients of class 'std::_String_alloc>'

and similarly for std::vector:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(679): warning C4251: 'std::_Vector_alloc>::_Mypair': class 'std::_Compressed_pair,std::allocator>>>,std::_Vector_val,std::allocator>>>,true>' needs to have dll-interface to be used by clients of class 'std::_Vector_alloc>'

While these are, in this contrived testcase, seemingly harmless and test tests run fine, I would like to fix them.

More seriously, if I use static libraries in place of DLLs, linking fails entirely:

c.lib(c.obj) : error LNK2001: unresolved external symbol "public: static unsigned __int64 const std::basic_string,class std::allocator >::npos" (?npos@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@2_KB)

I have also encountered this latter error trying to build other projects with VS2015.

My questions are:

  1. What exactly has changed in VS2015 to the string and vector classes?
  2. Am I exporting the string and vector classes properly here? I thought it matched the guidance here: https://support.microsoft.com/en-us/kb/168958
  3. What changes should I make to fix the static link error and DLL warnings so that it will work in both VS2015 and VS2013? (I'll leave 2012 for another day since it has a separate set of issues).

Many thanks for your insights, Roger

fschoenm
  • 1,391
  • 13
  • 32
Roger Leigh
  • 479
  • 4
  • 10
  • https://stackoverflow.com/questions/767579/exporting-classes-containing-std-objects-vector-map-etc-from-a-dll?rq=1 – Cory Kramer Jul 29 '15 at 16:06
  • Thanks, but I'm already following most of the guidance there. This doesn't address the issues with static linking and nor does it address the changes in VS2015. – Roger Leigh Jul 29 '15 at 18:01
  • This is more-or-less a duplicate of http://stackoverflow.com/q/22797418/103167 – Ben Voigt Nov 27 '15 at 22:00
  • @BenVoigt Note that the post you linked to is far more general and involves potentially using different VC versions; the question here does not. – Roger Leigh Nov 28 '15 at 23:40

2 Answers2

1

There is nothing that you can do to make this work across multiple versions of Visual C++. The class definitions are different in each version, so if you try to link mixed versions together, you violate the One Definition Rule.

No good ever comes of exporting Standard Library objects across DLL boundaries, I suggest you find a simpler way (using standard-layout types only) of passing the data around.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 2
    Note that this question is *not* about making things work across multiple visual C++ versions. It's about exporting and using STL types for use with a single VC version. – Roger Leigh Nov 28 '15 at 23:39
0

Removing the export of std::char_traits<char>:

b_EXPORT_TEMPLATE template struct b_EXPORT std::char_traits<char>;

removes the static linking errors.

Roger Leigh
  • 479
  • 4
  • 10