web-dev-qa-db-ja.com

libstdc ++でコンパイルされたライブラリとclang ++ -stdlib = libc ++を使用する

私はMac OS X(10.8.2)のC++で作業しており、最近、libc ++ stdlibを使用するclang ++コンパイラーで利用可能なC++ 11機能を使用する必要性を思いつきました。ただし、libstdc ++(MacPortsから提供)に対してコンパイルおよびリンクされたレガシーライブラリを使用する必要もあります。

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

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

68
user1690715

表示されているのは、インライン名前空間を使用してABIバージョン管理を実現することです。

その意味:

Libstdc ++ std::stringは、libc ++ std::stringとは異なるデータ構造です。前者は参照カウント設計ですが、後者はそうではありません。 API互換ですが、ABI互換ではありません。つまり、std::stringをlibstdc ++で作成し、それをlibc ++に対してリンクされている他のコードに渡すと、受信コードはlibc ++ std::stringを持っていると見なします。つまり受信者は、参照カウントをインクリメントまたはデクリメントする必要があるという手掛かりを持ちません。

インライン名前空間がないと、結果は実行時エラーになります。期待できる最高のものはクラッシュです。インライン名前空間では、この実行時エラーはリンク時エラーに変換されます。

プログラマにとって、libstdc ++ std::stringとlibc ++ std::stringは同じ型のように見えます。しかし、リンカにとっては、それらはまったく異なる型のように見えます(手がかりはstd::__1名前空間です)。そして、リンカーのビューは正しいです。 are完全に異なるタイプ。

そのため、いくつかのプリプロセッサフ​​ラグを操作して、リンクさせることができます。しかし、その場合、結果の実行時バグをデバッグするという悪魔になります。

あなたがしたいことをする唯一の方法は、これらのdylib間のインターフェースにstringなどのstd::型を含まないようにすることです。たとえば、代わりにcharの配列を渡すことができます。メモリの所有権をlibstdc ++にリンクされたコードからlibc ++にリンクされたコードに、またはその逆に転送することもできます(両方が同じmallocプールにドロップスルーします)。

92
Howard Hinnant