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

时间:2012-09-22 10:31:44

标签: c++ c++11 clang libstdc++ libc++

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

这样做,我得到了链接错误,因为遗留库的标题使用例如std::string,需要根据std::__1::basic_string解析(即{{1}的libc ++实现而不是std::string实现。

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

1 个答案:

答案 0 :(得分:90)

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

这意味着什么:

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

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

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

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

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