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

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

在这样做时,我得到了链接错误,因为遗留库的头部使用,例如,std::string,需要根据 std::__1::basic_string(例如,std::string的 libc + + 实现)而不是 std::basic_string实现来解析。

有没有一种方法可以在开发中混合使用这两个库(例如使用一些预处理器标志?)

21962 次浏览

您所看到的是使用 内联命名空间实现 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 池)。