73

私は Mac OS X (10.8.2) で C++ を使用していますが、最近、libc++ stdlib を使用する clang++ コンパイラで利用できる C++11 機能を使用する必要があることに気付きました。ただし、libstdc++ (MacPorts から取得) に対してコンパイルおよびリンクされたレガシー ライブラリも使用する必要があります。

そうすることで、リンク エラーが発生しました。たとえば、を使用するレガシー ライブラリのヘッダーは、実装ではなく(つまり、の libc++ 実装)std::stringに対して解決する必要があるためです。std::__1::basic_stringstd::stringstd::basic_string

開発中に 2 つのライブラリを混在させる方法はありますか (たとえば、いくつかのプリプロセッサ フラグを使用するなど)。

4

1 に答える 1

96

ご覧のとおり、インライン名前空間を使用して 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 プールにドロップされます)。

于 2012-09-22T17:57:35.903 に答える