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?)
Clang supports use of either LLVM's libc++ or GCC's libstdc++ implementation of the C++ standard library.
Clang has support for some of the features of the ISO C++ 2020 standard. You can use Clang in C++20 mode with the -std=c++20 option (use -std=c++2a in Clang 9 and earlier).
You can use Clang instead of GCC as a compiler for any package by overriding stdenv , which contains the compilation toolchain, with: stdenv = pkgs.
You can use Clang in C99 mode with the -std=c99 option.
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 a std::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 the std::__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 as string
. For example you could pass arrays of char
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With