25

特定の C++ ライブラリ (またはそれ以上のフレームワーク) に取り組んでいます。API の互換性だけでなく ABI も維持しながら、以前のバージョンとの下位互換性を持たせたいと考えています (Qt の素晴らしい仕事のように)。

私は Boost の多くの機能を使用していますが、ユーザーにまったく同じ (場合によっては古い) バージョンの Boost を強制的に使用させない限り、下位互換性が不可能になっているように思えます。

Boostのユーザーバージョンとの干渉を防ぐために、名前空間の周りに「プレフィックス」を作成/名前を変更する方法はありますか(Boostの1/2を書き換えずに)?

たとえば、私の libXYZ は Boost 1.33 を使用しており、 class がありboost::fooます。バージョン 1.35 ではバージョンboost::fooアップと新しいメンバーの追加が行われたため、boost::foo1.33 および 1.35 からは ABI に対応していません。そのため、libXYZ のユーザーは Boost 1.33 を使用するか、Boost 1.35 で libXYZ を再コンパイルする必要があります (XYZ がコンパイルしない方法で API が壊れている可能性があります)。

注:動的リンクが静的リンクに似ている ELF を使用する UNIX/Linux OS について話しているため、シンボルが干渉するため、2 つの異なるバージョンのライブラリとリンクすることはできません。

私が考える適切な解決策の 1 つは、Boost を他のプライベート名前空間に配置することです。そのため、libXYZ は::XYZ::boost::fooの代わりに使用し::boost::fooます。これにより、ユーザーが使用する可能性のある他のバージョンの Boost との衝突を防ぐことができます。

そのため、libXYZ は引き続き Boost 1.33 で動作し、静的または動的に他の名前空間にリンクされます。

  • Boost API を外部に公開しません。
  • 公開された API の安定したプライベート バージョンを保持します。

Boostでそのようなことを行う方法はありますか?

編集:最後に、ソース内のすべてのブースト シンボルの名前をカスタム シンボルに変更するスクリプトを作成することにしました。

根拠: コンパイラの可視性のサポートとは無関係に、ビルド プロセスを簡素化します。また、可視性は動的ライブラリでのみ機能し、静的では機能しないため、ライブラリの種類ごとに個別のビルドと依存関係が必要です。

スクリプトはhttp://art-blog.no-ip.info/files/rename.pyで入手できます。

編集 2: Boost BCP の最新バージョンは名前空間の名前変更をサポートしています。

4

4 に答える 4

30

基本的に、ライブラリへのパブリック インターフェイスが Boost を公開していないことを確認してください。内部で必要なだけいつでも使用できます。一般に、ライブラリのインターフェースを別のライブラリに依存させることは良くありません (STL のような標準ライブラリに依存しない限り)。Boost はほぼ「標準」ライブラリ カテゴリに収まりますが、その ABI は大幅に変更されるため、インターフェイスで使用しないでください。

Boost シンボルを公開しないようにするには、いくつかの方法があります。

A. でコンパイルし-fvisibility=hidden、すべてのパブリック シンボルを でマークし__attribute__((visibility("default")))ます。これを簡単にするためにマクロを使用できます。

#define ABI __attribute__((visibility("default")))

B. 次のようにします。

#pragma GCC visibility push(hidden)
#include <boost/whatever.hpp>
#pragma GCC visibility pop

また、エクスポートしたくない他のすべての内部シンボルをこれでラップするか、 で宣言する必要があります__attribute__((visibility("hidden")))。繰り返しますが、これを簡単にするためにマクロを使用できます。

#define INTERNAL __attribute__((visibility("hidden")))

これらのオプションの中で、私は A の方が気に入っています。なぜなら、どのシンボルがエクスポートされるかを明示的に考えるようになるため、不要なものを誤ってエクスポートすることがなくなるからです。

ところで、DSO の作成に関する詳細については、Ulrich Drepper のHow to Write Shared Libraries を参照してください。

于 2009-05-07T20:39:16.167 に答える
5

一般に、標準のCバインディング以外のC++のABIのタイプに依存することはできません。ただし、仮定の数に応じて、インターフェイスでC++をますます使用できます。

APIを安定したABIに変える手順に関するこのすばらしい記事を見つけました。たとえば、インターフェイス全体で標準C ++ライブラリ(またはBoost)データ型を渡さないでください。ライブラリの小さなバグ修正でも壊れることがあります。

ABI互換APIを公開するときに注意すべき問題の例は次のとおりです。

  • Windowsデバッグヒープ。すべての割り当てと割り当て解除が「モジュール」(つまり、実行可能ファイルまたはDLL)の同じ側にあることを確認する必要があります。
  • 壊れやすいバイナリインターフェイスの問題。システムの両側で一貫して同じコンパイラとライブラリを使用している場合でも、C ++では、.hファイルに何を公開するか、および割り当てがどこで行われるかについて注意する必要があります。

リンク先の記事をたどると、これらの問題やその他の問題の解決策が見つかります。

編集

また、C ++プロジェクトをCOMに変換することにより、COMインターフェイスがどのように機能するかを説明するMicrosoftが公開した興味深い記事を見つけました。MicrosoftがCOMを開発した主な理由の1つは、C ++が抱える脆弱なバイナリインターフェイスの問題を解決し、オブジェクト指向APIを公開してDLLを出荷できるようにすることであると私は信じています。

于 2009-05-08T00:42:13.853 に答える
3

安定した API/ABI インターフェースを維持するために、abi-compliance-checkerツールの使用を検討してください。

于 2009-08-07T23:12:13.113 に答える
0

次のようなことができるはずです。

namespace XYZ
{
#include <boost/my_library.hpp>
}

そして、ブースト ヘッダーを名前空間 XYZ にダンプする必要があります。ただし、これはヘッダーのみのライブラリでのみ機能することに注意してください。

于 2009-05-07T20:46:03.420 に答える