0

When trying to link with a dynamic library I built with Xcode 6.3.2, all of my calls to class functions that have parameters of std::string refuse to link:

Undefined symbols for architecture x86_64:
  “MyClass::Bogus(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)”,…

The dylib’s .h file IS being included, and the public class member is prototyped as:

int Bogus(std::string& aStringRef, bool verbose);

INTERESTINGLY, if I change the type of that first std::string parameter to long (and call it with a long as the first parameter), there is no link error. So I know I am definitely linking with the dylib I built.

For my dylib, the Apple LLVM 6.1 C++ standard library is set to the default (libstdc++).

The code where I am making the call from is itself a .dylib, and is being compiled and linked not from Xcode, but entirely from a makefile. The version of c++ used to compile from that makefile is:

Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix

One thing that seems suspicious to me is that the calling code is compiled using "-std=c++1y”, which may be using a standard library for C++14. Could there be a conflict between the standard library being linked for the calling program with the one I selected for building the dylib? (my dylib’s code is being compiled with compiler dialect = GNU++98)

SMGreenfield
  • 1,680
  • 19
  • 35
  • It looks like your code is compiled with libc++. – Kerrek SB Aug 08 '15 at 22:19
  • @KerrekSB - running tool -L on my linked dylib shows: c /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0) – SMGreenfield Aug 08 '15 at 23:10
  • 1
    Is /usr/lib/libstdc++.6.dylib a symlink by any chance? – Kerrek SB Aug 08 '15 at 23:39
  • @KerrekSB -- UH, OH -- it is: libstdc++.6.dylib -> libstdc++.6.0.9.dylib But in this case -- where the dylib is both created and (for now) called on the same machine -- how would that create the above problem? And could changing that resolve the original problem? – SMGreenfield Aug 08 '15 at 23:45
  • No, that's fine, I was wondering if it's a symlink to libc++... – Kerrek SB Aug 08 '15 at 23:57

1 Answers1

2

It's hard to pass standard library objects between different binary modules, because their binary representations and implementation details are not standardized.

To make it work, you'd need to make sure all of the modules are using the same - and probably the same version of the - compiler, standard library implementation and all related compilation settings (exceptions, iterator debugging, etc)... Which basically defeats the purpose of having a dynamic library in the first place.

When passing data around, you should either stick to simple pointers (c-strings, data buffers) or introduce some custom, more transparent data types.

See the following answers for some concrete solutions:

Passing std::string in a library API

Passing reference to STL vector over dll boundary

Community
  • 1
  • 1
ing
  • 81
  • 3
  • Well, this is a sad state of affairs! In our case, the it has always been intended for two dylib to be built at the same time from the same makefile -- we were just testing by building the called dylib in Xcode. I wonder if using a Boost string might make the process more resistant to binary incompatibilities? – SMGreenfield Aug 09 '15 at 00:29
  • @SMGreenfield If you need a std::string specifically, the simplest solution is probably to implement a minimal std::string wrapper in one of your modules and use in all of the cross-library interfaces. – ing Aug 09 '15 at 04:11