dart:ffi を使用した C 相互運用
- サンプルファイルのダウンロード
- C ライブラリのバンドルと読み込み
- ネイティブ型とのインターフェース
- package:ffigen で FFI バインディングを生成します
- ネイティブアセットのビルドとバンドル
Dart Native プラットフォームで実行される Dart モバイル、コマンドライン、およびサーバーアプリは、dart:ffi
ライブラリを使用してネイティブ C API を呼び出し、ネイティブメモリの読み取り、書き込み、割り当て、および割り当て解除を行うことができます。FFI は 外部関数インターフェース の略です。同様の機能の他の用語には、ネイティブインターフェース および 言語バインディング があります。
API ドキュメントは、dart:ffi
API リファレンスで入手できます。
サンプルファイルのダウンロード
#このガイドの例を使用するには、完全な ffi サンプルディレクトリをダウンロードしてください。これには、dart:ffi
ライブラリの使い方を示す次の例が含まれています。
例 | 説明 |
---|---|
hello_world | 引数と戻り値のない C 関数を呼び出す方法。 |
primitives | int またはポインタである引数と戻り値を持つ C 関数を呼び出す方法。 |
structs | 文字列を C との間で受け渡し、単純および複雑な C 構造体を処理するために構造体を使用する方法。 |
test_utils | これらのすべての例の共通のテストユーティリティ。 |
hello_world サンプルを確認
#hello_world 例には、C ライブラリを呼び出すために必要な最小限のコードが含まれています。この例は、前のセクションでダウンロードした samples/ffi
にあります。
ファイル
#hello_world
の例には、次のファイルがあります。
ソースファイル | 説明 |
---|---|
hello.dart | C ライブラリの hello_world() 関数を使用する Dart ファイル。 |
pubspec.yaml | SDK の下限が 3.4 の Dart pubspec ファイル。 |
hello_library/hello.h | hello_world() 関数を宣言します。 |
hello_library/hello.c | hello.h をインポートし、hello_world() 関数を定義する C ファイル。 |
hello_library/hello.def | DLL のビルド時に使用される情報を指定するモジュール定義ファイル。 |
hello_library/CMakeLists.txt | C コードを動的ライブラリにコンパイルするための CMake ビルドファイル。 |
C ライブラリをビルドすると、libhello.dylib
(macOS)、libhello.dll
(Windows)、または libhello.so
(Linux) という名前の動的ライブラリファイルを含むいくつかのファイルが作成されます。
ビルドと実行
#動的ライブラリをビルドし、Dart アプリを実行するコマンドは、次のシリーズのようになります。
$ cd hello_library
$ cmake .
...
$ make
...
$ cd ..
$ dart pub get
$ dart run hello.dart
Hello World
dart:ffi を活用する
#dart:ffi
ライブラリを使用して C 関数を呼び出す方法については、hello.dart
ファイルを確認してください。このセクションでは、このファイルの内容について説明します。
dart:ffi
をインポートします。dartimport 'dart:ffi' as ffi;
動的ライブラリのパスを格納するために使用する path ライブラリをインポートします。
dartimport 'dart:io' show Platform, Directory; import 'package:path/path.dart' as path;
C 関数の FFI 型シグネチャを持つ typedef を作成します。
dart:ffi
ライブラリに従って最もよく使用される型については、ネイティブ型とのインターフェースを参照してください。darttypedef hello_world_func = ffi.Void Function();
C 関数を呼び出すときに使用する変数の
typedef
を作成します。darttypedef HelloWorld = void Function();
動的ライブラリのパスを格納する変数を作成します。
dartvar libraryPath = path.join(Directory.current.path, 'hello_library', 'libhello.so'); if (Platform.isMacOS) { libraryPath = path.join(Directory.current.path, 'hello_library', 'libhello.dylib'); } else if (Platform.isWindows) { libraryPath = path.join(Directory.current.path, 'hello_library', 'Debug', 'hello.dll'); }
C 関数を含む動的ライブラリを開きます。
dartfinal dylib = ffi.DynamicLibrary.open(libraryPath);
C 関数への参照を取得し、それを変数に入れます。このコードでは、手順 2 および 3 の
typedefs
と、手順 4 の動的ライブラリ変数を使用します。dartfinal HelloWorld hello = dylib .lookup<ffi.NativeFunction<hello_world_func>>('hello_world') .asFunction();
C 関数を呼び出します。
darthello();
hello_world
の例を理解したら、その他の dart:ffi
例を参照してください。
C ライブラリのバンドルと読み込み
#ネイティブ C ライブラリをバンドル/パッケージ化/配布してロードする方法は、プラットフォームとライブラリの種類によって異なります。
方法については、次のページと例を参照してください。
- Android アプリ向けの Flutter
dart:ffi
- iOS アプリ向けの Flutter
dart:ffi
- macOS アプリ向けの Flutter
dart:ffi
dart:ffi
の例
ネイティブ型とのインターフェース
#dart:ffi
ライブラリは、NativeType
を実装し、C のネイティブ型を表す複数の型を提供します。一部のネイティブ型をインスタンス化できます。他のネイティブ型は、型シグネチャのマーカーとしてのみ使用できます。
これらの型シグネチャマーカーをインスタンス化できます
#次のネイティブ型は、型シグネチャのマーカーとして使用できます。それらまたはそのサブタイプは、Dart コードでインスタンス化できます。
Dart 型 | 説明 |
---|---|
Array | 固定サイズのアイテムの配列。型固有の配列のスーパータイプ。 |
Pointer | ネイティブ C メモリへのポインタを表します。 |
Struct | すべての FFI 構造体型のスーパータイプ。 |
Union | すべての FFI 共用体型のスーパータイプ。 |
型シグネチャマーカーとしてのみ機能します
#次のリストは、型シグネチャのマーカーとして機能するプラットフォームに依存しないネイティブ型を示しています。これらは、Dart コードでインスタンス化できません。
Dart 型 | 説明 |
---|---|
Bool | C のネイティブ bool を表します。 |
Double | C のネイティブ 64 ビット double を表します。 |
Float | C のネイティブ 32 ビット float を表します。 |
Int8 | C のネイティブ符号付き 8 ビット整数を表します。 |
Int16 | C のネイティブ符号付き 16 ビット整数を表します。 |
Int32 | C のネイティブ符号付き 32 ビット整数を表します。 |
Int64 | C のネイティブ符号付き 64 ビット整数を表します。 |
NativeFunction | C の関数型を表します。 |
Opaque | C のすべての不透明型のスーパータイプ。 |
Uint8 | C のネイティブ符号なし 8 ビット整数を表します。 |
Uint16 | C のネイティブ符号なし 16 ビット整数を表します。 |
Uint32 | C のネイティブ符号なし 32 ビット整数を表します。 |
Uint64 | C のネイティブ符号なし 64 ビット整数を表します。 |
Void | C の void 型を表します。 |
また、ABI固有のマーカーネイティブ型も多数存在し、これらはAbiSpecificIntegerを拡張しています。これらの型が特定のプラットフォームでどのようにマッピングされるかについては、次の表にリンクされているAPIドキュメントを参照してください。
Dart 型 | 説明 |
---|---|
AbiSpecificInteger | すべてのABI固有の整数型のスーパータイプです。 |
Int | C言語のint 型を表します。 |
IntPtr | C言語のintptr_t 型を表します。 |
Long | C言語のlong int (long ) 型を表します。 |
LongLong | C言語のlong long 型を表します。 |
Short | C言語のshort 型を表します。 |
SignedChar | C言語のsigned char 型を表します。 |
Size | C言語のsize_t 型を表します。 |
UintPtr | C言語のuintptr_t 型を表します。 |
UnsignedChar | C言語のunsigned char 型を表します。 |
UnsignedInt | C言語のunsigned int 型を表します。 |
UnsignedLong | C言語のunsigned long int 型を表します。 |
UnsignedLongLong | C言語のunsigned long long 型を表します。 |
UnsignedShort | C言語のunsigned short 型を表します。 |
WChar | C言語のwchar_t 型を表します。 |
package:ffigen
でFFIバインディングを生成する
#大規模なAPIサーフェスの場合、Cコードと統合するDartバインディングを作成するには時間がかかることがあります。DartにCヘッダーファイルからFFIラッパーを作成させるには、package:ffigen
バインディングジェネレーターを使用します。
ネイティブアセットのビルドとバンドル
#ネイティブアセット機能は、ネイティブコードに依存するDartパッケージの配布に関連する多くの問題を解決するはずです。これは、FlutterおよびスタンドアロンのDartアプリケーションのビルドに関与するさまざまなビルドシステムと統合するための統一されたフックを提供することにより実現します。
この機能は、Dartパッケージがネイティブコードに依存して使用する方法を簡素化するはずです。ネイティブアセットは、次のメリットを提供する必要があります。
- パッケージの
hook/build.dart
ビルドフックを使用してネイティブコードをビルドするか、バイナリを取得します。 build.dart
ビルドフックが報告するネイティブAsset
をバンドルします。assetId
を使用して、宣言的な@Native<>() extern
関数を介して実行時にネイティブアセットを利用できるようにします。
ネイティブ実験にオプトインすると、flutter (run|build)
およびdart (run|build)
コマンドは、Dartコードとともにネイティブコードをビルドおよびバンドルします。
native_add_library
の例を確認する
#native_add_library
の例には、DartパッケージでCコードをビルドおよびバンドルするための最小限のコードが含まれています。
この例には、次のファイルが含まれています。
ソースファイル | 説明 |
---|---|
src/native_add_library.c | add のコードを含むCファイル。 |
lib/native_add_library.dart | FFIを介してアセットpackage:native_add_library/native_add_library.dart でC関数add を呼び出すDartファイル。(アセットIDはデフォルトでライブラリURIになることに注意してください。) |
test/native_add_library_test.dart | ネイティブコードを使用するDartテスト。 |
hook/build.dart | src/native_add_library.c をコンパイルし、IDpackage:native_add_library/native_add_library.dart を持つコンパイル済みアセットを宣言するためのビルドフック。 |
DartまたはFlutterプロジェクトがpackage:native_add_library
に依存する場合、run
、build
、およびtest
コマンドでhook/build.dart
ビルドフックを呼び出します。native_add_app
の例は、native_add_library
の使用例を示しています。
ネイティブアセット API ドキュメントを確認
#次のパッケージのAPIドキュメントを見つけることができます
- Dart FFIのネイティブアセットの詳細については、
Native
およびDefaultAsset
のdart:ffi
APIリファレンスを参照してください。 hook/build.dart
ビルドフックの詳細については、package:native_assets_cli
APIリファレンスを参照してください。
実験にオプトイン
#実験を有効にしてフィードバックを提供する方法については、次のトラッキングイシューを参照してください。
特に明記されていない限り、このサイトのドキュメントは Dart 3.5.3 を反映しています。ページは 2024-05-30 に最終更新されました。 ソースを表示または問題を報告する。