C++ ライブラリ サポート

Android プラットフォームには、ごく最小限の C++ ランタイム サポート ライブラリ(libstdc++)が用意されています。この最小限のサポートには、以下のような機能は含まれていません。

  • 標準 C++ ライブラリ サポート(ごく一部のヘッダーを除く)
  • C++ 例外サポート
  • RTTI サポート

NDK はこの既定のライブラリと併用するヘッダーを提供します。さらに、追加機能を提供する数多くのヘルパー ランタイムも用意されています。 このページでは、このヘルパー ランタイムとその特性、ならびのその使用方法について説明します。

ヘルパー ランタイム

表 1 に NDK で使用できるランタイムの名前、簡単な説明、機能を示します。

表 1 NDK ランタイムと機能

名前 説明 機能
libstdc++(既定) 既定の最小限のシステム C++ ランタイム ライブラリ該当せず
gabi++_static GAbi++ ランタイム(静的)C++ 例外と RTTI
gabi++_shared GAbi++ ランタイム(共有)C++ 例外と RTTI
stlport_static STLport ランタイム(静的) C++ 例外と RTTI、標準ライブラリ
stlport_shared STLport ランタイム(共有) C++ 例外と RTTI、標準ライブラリ
gnustl_static GNU STL(静的) C++ 例外と RTTI、標準ライブラリ
gnustl_shared GNU STL(共有) C++ 例外と RTTI、標準ライブラリ
c++_static LLVM libc++ ランタイム(静的) C++ 例外と RTTI、標準ライブラリ
c++_shared LLVM libc++ ランタイム(共有) C++ 例外と RTTI、標準ライブラリ

ランタイムの設定方法

Application.mk ファイルの APP_STL 変数で使用するランタイムを指定します。 表 1 の「名前」列の値を設定に使用します。 次に例を示します。

APP_STL := gnustl_static

アプリ用に選択できるランタイムは 1 つだけで、Application.mk でのみ指定できます。

NDK ビルドシステムを使用しなくても、STLport、libc++、GNU STL は使用できます。独自のツールチェーンでこれらのランタイムを使用する方法については、スタンドアロン ツールチェーンで詳細をご覧ください。

ランタイムの特性

libstdc++(既定のシステム ランタイム)

このランタイムで提供するのは次のヘッダーのみです。これ以上のサポートはしていません。

  • cassert
  • cctype
  • cerrno
  • cfloat
  • climits
  • cmath
  • csetjmp
  • csignal
  • cstddef
  • cstdint
  • cstdio
  • cstdlib
  • cstring
  • ctime
  • cwchar
  • new
  • stl_pair.h
  • typeinfo
  • utility

GAbi++ ランタイム

このラインタイムは既定のランタイムと同じヘッダーを提供しますが、追加で RTTI(ランタイム タイプ情報)と例外処理がサポートされています。

STLport ランタイム

このランタイムは STLport(http://www.stlport.org)の Android ポートです。 C++ 標準ライブラリ ヘッダーのフルセットを提供します。 GAbi++ の独自のインスタンスを組み込むことで、RTTI と例外処理もサポートしています。

このランタイムは共有バージョンと静的バージョンの利用が可能ですが、共有バージョンを利用することをお勧めします。 詳細については、静的ランタイムをご覧ください。

共有ライブラリ ファイルの名前は、他のプラットフォームで一般的な libstdc++.so ではなく、libstlport_shared.so です。

静的ライブラリと共有ライブラリのオプションに加えて、次の行を Application.mk ファイルに追加するか、ビルド前に環境に設定することでも、NDK にソースからライブラリを強制的にビルドさせることができます。

STLPORT_FORCE_REBUILD := true

GNU STL ランタイム

このランタイムは GNU 標準 C++ ライブラリ(libstdc++-v3)です。共有ライブラリ ファイルの名前は libgnustl_shared.so です。

libc++ ランタイム:

このランタイムは LLVM libc++ の Android ポートです。共有ライブラリ ファイルの名前は libc++_shared.so です。

既定では、このランタイムは -std=c++11 を使用してコンパイルします。GNU libstdc++ と同様に、例外または RTTI サポートを明示的に有効にする必要があります。 詳細については、C++ 例外RTTI をご覧ください。

NDK は libc++ 向けに事前にビルドされた静的ライブラリと共有ライブラリを提供しますが、次の行を Application.mk ファイルに追加するか、ビルドの前に環境に設定することでも、NDK にソースから libc++ を強制的に再ビルドさせることができます。

LIBCXX_FORCE_REBUILD := true

アトミック サポート

<atomic> を取り込んだ場合、libatomic も必要となる場合があります。ndk-build を使用している場合は次の行を追加します。

LOCAL_LDLIBS += -latomic

独自のツールチェーンを使用している場合は次の行を使用します。

-latomic

互換性

NDK の libc++ は安定していません。すべてのテストに通るわけでなく、テストスイートは包括的ではありません。次のような既知の問題があります。

  • ARM で c++_shared を使用すると、例外がスローされたときにクラッシュする可能性があります。
  • wchar_t とロケール API のサポートは限定的です。

使用している NDK リリースの変更ログの「既知の問題」セクションも確認してください。

警告: サポートされていないロケールに変更しようとした場合、失敗にはなりません。 操作は成功しますが、ロケールは変更されず、logcat に次のメッセージが表示されます。

newlocale() WARNING: Trying to set locale to en_US.UTF-8 other than "", "C" or "POSIX"

重要な考慮事項

C++ 例外

NDKr5 以降の NDK のすべてのバージョンでは、NDK ツールチェーンによって、例外処理をサポートする C++ ランタイムが使用できます。 ただし、以前のリリースとの互換性を確保するため、NDK ツールチェーンはデフォルトで、-fno-exceptions サポートを使用してすべての C++ ソースをコンパイルします。 アプリ全体、または個々のモジュールに対して、C++ 例外を有効にできます。

アプリ全体で例外処理サポートを有効にするには、次の行を Application.mk ファイルに追加します。個々のモジュールで例外処理サポートを有効にするには、次の行を各モジュールの Android.mk ファイルにそれぞれ追加します。

APP_CPPFLAGS += -fexceptions

RTTI

NDKr5 以降の NDK のすべてのバージョンでは、NDK ツールチェーンによって、RTTI をサポートする C++ ランタイムが使用できます。 ただし、以前のリリースとの互換性を確保するため、NDK ツールチェーンはデフォルトで、 -fno-rtti を使用してすべての C++ ソースをコンパイルします。

アプリ全体で RTTI サポートを有効にするには、次の行を Application.mk ファイルに追加します。

APP_CPPFLAGS += -frtti
個々のモジュールで RTTI サポートを有効にするには、次の行を各モジュールの Android.mk ファイルにそれぞれ追加します。
LOCAL_CPP_FEATURES += rtti
または、次の行を使用できます。
LOCAL_CPPFLAGS += -frtti

静的ランタイム

C++ ランタイムの静的ライブラリ バリアントと複数のバイナリをリンクすると、予期しない動作が発生する可能性があります。 たとえば、次のような動作が考えられます。

  • メモリが 1 つのライブラリに割り当てられ、他のライブラリで解放されると、メモリ漏洩またはヒープ破壊が発生する。
  • 例外が libbar.so で検出されずに libfoo.so で報告されると、アプリがクラッシュする。
  • std::cout のバッファリングが正しく動作しない。

さらに、2 つの共有ライブラリ、または 1 つのライブラリと 1 つの実行可能ファイルを同じ静的ランタイムに対してリンクした場合、各共有ライブラリの最終バイナリ イメージに、ランタイムのコードのコピーが含まれます。 ランタイム コードのインスタンスが複数存在すると、ランタイムが内部で使用または提供する特定のグローバル変数が重複するため、問題が発生する可能性があります。

この問題は単一の共有ライブラリから構成されるプロジェクトには該当しません。たとえば、stlport_static に対してリンクすると、アプリは正しく動作すると期待できます。 プロジェクトに複数の共有ライブラリ モジュールが必要な場合、C++ ランタイムの共有ライブラリ バリアントを使用することをお勧めします。

共有ランタイム

アプリが Android 4.3(Android API レベル 18)以前の Android のバージョンをターゲットにしており、特定の C++ ランタイムの共有ライブラリ バリアントを使用している場合、共有ライブラリを、それに依存する他のすべてのライブラリよりも先に読み込む必要があります。

たとえば、次のモジュールから構成されるアプリがあるとします。

  • libfoo.so
  • libfoo.so で使用される libbar.so
  • libfoo と libbar の両方で使用される libstlport_shared.so

依存関係と逆の順序でライブラリを読み込む必要があります。

    static {
      System.loadLibrary("stlport_shared");
      System.loadLibrary("bar");
      System.loadLibrary("foo");
    }

注: System.loadLibrary() を呼び出すときは、lib 接頭辞を使用しないでください。

ライセンス

STLport は、BSD スタイルのオープンソース ライセンスの下に使用が許諾されています。STLport の詳細については、$NDK/sources/cxx-stl/stlport/README をご覧ください。

GNU libstdc++ には GPLv3 ライセンスが適用されます。LGPLv2 または LGPLv3 は適用されません。詳細については、GCC ウェブサイトのライセンスをご覧ください。

LLVMlibc++ はイリノイ大学の「BSD に類似した」ライセンスと MIT ライセンスの双方の下に使用が許諾されています。