I am working in C++ under Mac OS X (10.8.2) and I recently came up with the need of using C++11 features, which are available through the clang++ compiler using the libc++ stdlib. However, I also need to use some legacy library compiled and linked against libstdc++ (coming from MacPorts).
In doing so, I got linking errors, since the headers of the legacy libraries using, e.g., std::string
, required to be resolved against the std::__1::basic_string
(i.e., the libc++ implementation of std::string
) instead of the std::basic_string
implementation.
Is there a way to mix the two libraries in development (e.g. by using some preprocessors flags?)
What you're seeing is the use of inline namespaces to achieve ABI versioning.
What that means:
The libstdc++
std::string
is a different data structure than the libc++std::string
. The former is a reference counted design, whereas the latter is not. Although they are API compatible, they are not ABI compatible. That means that if you construct astd::string
with libstdc++, and then pass it to other code that is linked against libc++, the receiving code would think it has a libc++std::string
. I.e. the receiver would not have a clue that it should be incrementing or decrementing reference counts.Without inline namespaces, the result would be a run time error. The best you could hope for is a crash. With inline namespaces this run time error is translated into a link time error.
To you the programmer the libstdc++
std::string
and the libc++std::string
look like the same type. But to the linker, they look like completely different types (the clue is thestd::__1
namespace). And the linker's view is correct. They are completely different types.So yes, you could manipulate some preprocessor flags to get things to link. But then you would have a devil of a time debugging the resultant run time bugs.
The only way to do what you want to is to make the interfaces between these dylibs not involve
std::
types such asstring
. For example you could pass arrays ofchar
instead. You can even transfer memory ownership from libstdc++-linked code to libc++-linked code and vice-versa (they will both drop through to the same malloc pool).