我在Mac OS X(10.8.2)下使用C ++工作,最近我想出了使用C ++ 11功能的需求,这些功能可以通过使用libc ++ stdlib的clang ++编译器获得。 但是,我还需要使用一些针对libstdc ++编译和链接的遗留库(来自MacPorts)。
这样做,我得到了链接错误,因为遗留库的标题使用例如std::string
,需要根据std::__1::basic_string
解析(即{{1}的libc ++实现而不是std::string
实现。
有没有办法在开发中混合两个库(例如通过使用一些预处理器标志?)
答案 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池)。