使用带有clang ++ -stdlib = libc ++的libstdc ++编译库

use*_*715 68 c++ clang libstdc++ c++11 libc++

我在Mac OS X(10.8.2)下使用C++工作,最近我想出了使用C++ 11功能的需求,这些功能可以通过使用libc ++ stdlib的clang ++编译器获得.但是,我还需要使用一些针对libstdc ++编译和链接的遗留库(来自MacPorts).

在这样做时,我得到了链接错误,因为遗留库的标题使用,例如std::string,需要解决std::__1::basic_string(即,libc ++实现std::string)而不是std::basic_string实现.

有没有办法在开发中混合两个库(例如,通过使用一些预处理器标志?)

How*_*ant 92

您所看到的是使用内联命名空间来实现ABI版本控制.

那意味着什么:

libstdc ++ std::string是一个与libc ++不同的数据结构std::string.前者是参考计数设计,而后者不是.虽然它们与API兼容,但它们不兼容ABI.这意味着如果std::string使用libstdc ++ 构造一个,然后将其传递给与libc ++链接的其他代码,接收代码会认为它具有libc ++ std::string.即接收者不会知道它应该递增或递减参考计数.

如果没有内联命名空间,结果将是运行时错误.你可能希望的最好的是崩溃.使用内联命名空间,此运行时错误将转换为链接时错误.

对于程序员来说,libstdc ++ std::string和libc ++ std::string看起来是相同的类型.但是对于链接器,它们看起来像完全不同的类型(线索是std::__1命名空间).链接器的视图是正确的.它们完全不同的类型.

所以,是的,你可以操纵一些预处理器标志来获取链接的东西.但是那时你会有一个时间调试结果运行时错误.

做你想做的事的唯一方法是使这些dylib之间的接口不涉及std::类型string.例如,您可以传递数组char.您甚至可以将内存所有权从libstdc ++链接代码转移到libc ++链接代码,反之亦然(它们都将转移到同一个malloc池).

  • 最大的希望是:只要不跨dylib边界传递版本化符号,就可以在一个过程中混合使用两个库.如果你不小心做了,错误会在链接时发现.您可以跨dylib边界抛出`std :: exception`派生的异常,并跨dylib边界传输内存所有权.我怀疑这可能是更好的ABI兼容性,而不是gcc将提供自己的4.2版本.请注意,通过std规范,甚至`std :: string`在C++ 98/03和C++ 11之间也不兼容ABI.前者被广泛重新计算,而后者被禁止. (13认同)
  • 因此,总结一下,没有希望使用遗留库(即,与libstdc ++链接的库)和libc ++.这真的是一个严重的限制 (7认同)
  • 另一个例子:pre-C++ 11 gcc`std :: list`与`std :: list`的C++ 11规范不兼容.换句话说:您对libc ++的评论同样适用于(如果不是更多)libstdc ++的C++ 11之前的版本.libc ++不再是与C++ 11 libstdc ++之前的兼容,而不是符合C++ 11的libstdc ++. (3认同)
  • 是不是可以为std :: string创建一个赋值重载到std :: _ 1 :: string,反之亦然? (3认同)
  • @ user1690715可以更准确地说,当他们在API上公开STL对象时,没有希望互操作库与两个运行时构建 - 这一直是一个非常冒险的命题. (2认同)