dart:ffi を使用したネイティブ macOS コードへのバインド
Flutter モバイル アプリとデスクトップ アプリでは、ダーツ:ffiネイティブ C API を呼び出すためのライブラリ。FFIを意味する外部関数インターフェイス。同様の機能を表すその他の用語には次のものがあります。ネイティブインターフェースと言語のバインディング。
ライブラリまたはプログラムが FFI ライブラリを使用できるようになる前に ネイティブ コードにバインドするには、次のことを確認する必要があります。 ネイティブ コードがロードされ、そのシンボルが Dart に表示されます。 このページはコンパイル、パッケージ化、 Flutter プラグインまたはアプリ内で macOS ネイティブ コードをロードします。
このチュートリアルでは、C/C++ をバンドルする方法を説明します。 Flutter プラグイン内のソースを使用してバインドします。 macOS 上の Dart FFI ライブラリ。 このチュートリアルでは、C 関数を作成します 32ビット加算を実装し、 「native_add」という名前の Dart プラグインを通じてそれを公開します。
動的リンクと静的リンク
ネイティブ ライブラリはアプリにリンクできます。 動的または静的に。静的にリンクされたライブラリ アプリの実行可能イメージに埋め込まれており、 アプリの起動時に読み込まれます。
静的にリンクされたライブラリのシンボルは、
を使用してロードされました793ae93e-a602-4f70-a04c-989205290c66またDynamicLibrary.process
。
対照的に、動的にリンクされたライブラリは分散されます。
アプリ内の別のファイルまたはフォルダーに、
そしてオンデマンドでロードされます。 macOS では、動的にリンクされた
ライブラリはとして配布されます.framework
フォルダ。
動的にリンクされたライブラリは、
ダーツの使い方DynamicLibrary.open
。
API ドキュメントは Dart 開発チャネルから入手できます。Dart API リファレンス ドキュメント。
ステップ 1: プラグインを作成する
すでにプラグインをお持ちの場合は、この手順をスキップしてください。
「native_add」というプラグインを作成するには、 以下をせよ:
$ flutter create --platforms=macos --template=plugin native_add
$ cd native_add
ステップ 2: C/C++ ソースを追加する
macOS ビルド システムに次のことを通知する必要があります。 ネイティブコードなのでコードをコンパイルできる そして最終的なアプリケーションに適切にリンクされます。
ソースをmacos
フォルダ、
CocoaPods ではソースを含めることができないため、
の上podspec
ファイル。
FFI ライブラリは C シンボルに対してのみバインドできます。
したがって、C++ では、これらのシンボルをマークする必要がありますextern C
。
また、次のことを示す属性も追加する必要があります。
シンボルは Dart から参照されます。
リンカーがシンボルを破棄しないようにするため
リンク時の最適化中。
例えば、
という名前の C++ ファイルを作成しますmacos/Classes/native_add.cpp
、
次の手順を使用してください。 (テンプレートは
このファイルはすでに作成されています)。
プロジェクトのルート ディレクトリ:
cat > macos/Classes/native_add.cpp << EOF
#include <stdint.h>
extern "C" __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t x, int32_t y) {
return x + y;
}
EOF
macOS では、ファイルを静的にリンクするように Xcode に指示する必要があります。
- Xcode で開きます
Runner.xcworkspace
。 - C/C++/Objective-C/Swift を追加します。 ソース ファイルを Xcode プロジェクトに追加します。
ステップ 3: FFI ライブラリを使用してコードをロードする
この例では、次のコードを追加できますlib/native_add.dart
。ただし、その場所は、
Dart バインディング コードは重要ではありません。
まず、DynamicLibrary
ハンドル
ネイティブコード。
import 'dart:ffi'; // For FFI
final DynamicLibrary nativeAddLib = DynamicLibrary.process();
周囲のライブラリへのハンドルを使用すると、
を解決できますnative_add
シンボル:
final int Function(int x, int y) nativeAdd = nativeAddLib
.lookup<NativeFunction<Int32 Function(Int32, Int32)>>('native_add')
.asFunction();
ようやく、呼び出すことができます。これを実証するには
自動生成された「サンプル」アプリ (example/lib/main.dart
):
// Inside of _MyAppState.build:
body: Center(
child: Text('1 + 2 == ${nativeAdd(1, 2)}'),
),
その他の使用例
iOSとmacOS
動的にリンクされたライブラリは、次のように自動的にロードされます。
アプリ起動時の動的リンカー。彼らの構成員
シンボルは次を使用して解決できますDynamicLibrary.process
。
次のコマンドを使用してライブラリへのハンドルを取得することもできますDynamicLibrary.open
~の範囲を制限する
シンボル解決が行われますが、Apple がどのように解決するかは不明です。
レビュープロセスがこれを処理します。
アプリケーションバイナリに静的にリンクされたシンボル
を使用して解決できますDynamicLibrary.executable
またDynamicLibrary.process
。
プラットフォームライブラリ
プラットフォーム ライブラリにリンクするには、 次の手順を使用してください。
- Xcode で開きます
Runner.xcworkspace
。 - ターゲット プラットフォームを選択します。
- クリック+の中にリンクされたフレームワークとライブラリセクション。
- リンクするシステム ライブラリを選択します。
ファーストパーティライブラリ
ファーストパーティのネイティブ ライブラリは、次のいずれかを含めることができます。
ソースとして、または(署名付き)として.framework
ファイル。
おそらく静的にリンクされたものを含めることが可能です
アーカイブも可能ですが、テストが必要です。
ソースコード
ソースコードに直接リンクするには、 次の手順を使用してください。
- Xcode で開きます
Runner.xcworkspace
。 - C/C++/Objective-C/Swift を追加します。 ソース ファイルを Xcode プロジェクトに追加します。
-
次のプレフィックスを追加します エクスポートされたシンボル宣言 Dart からは見えます:
C/C++/目的 C
extern "C" /* <= C++ only */ __attribute__((visibility("default"))) __attribute__((used))
迅速
@_cdecl("myFunctionName")
コンパイルされた (動的) ライブラリ
コンパイルされた動的ライブラリにリンクするには、 次の手順を使用してください。
- 正しく署名されていれば、
Framework
ファイルは存在しますが、 開けるRunner.xcworkspace
。 - フレームワーク ファイルを埋め込みバイナリセクション。
- また、リンクされたフレームワークとライブラリXcode のターゲットのセクション。
コンパイル済み (動的) ライブラリ (macOS)
クローズドソースライブラリを追加するにはFlutter macOS デスクトップアプリ、 次の手順を使用してください。
- Flutter デスクトップの手順に従って作成します。 Flutter デスクトップ アプリ。
- を開きます
yourapp/macos/Runner.xcworkspace
Xcodeで。- プリコンパイルされたライブラリをドラッグします (
libyourlibrary.dylib
) の中へRunner/Frameworks
。 - クリック
Runner
そして、に行きますBuild Phases
タブ。- 引っ張る
libyourlibrary.dylib
にCopy Bundle Resources
リスト。 - 下
Embed Libraries
、 チェックCode Sign on Copy
。 - 下
Link Binary With Libraries
、 ステータスをに設定Optional
。 (動的リンクを使用しています。 静的にリンクする必要はありません。)
- 引っ張る
- クリック
Runner
そして、に行きますGeneral
タブ。- 引っ張る
libyourlibrary.dylib
にフレームワーク、 ライブラリと埋め込みコンテンツリスト。 - 選択する埋め込みと署名。
- 引っ張る
- クリックランナーそして、に行きますビルド設定タブ。
- の中に検索パスセクションで設定するライブラリ検索パスパスを含めるには
どこ
libyourlibrary.dylib
位置しています。
- の中に検索パスセクションで設定するライブラリ検索パスパスを含めるには
どこ
- プリコンパイルされたライブラリをドラッグします (
- 編集
lib/main.dart
。- 使用
DynamicLibrary.open('libyourlibrary.dylib')
シンボルに動的にリンクします。 - ウィジェット内のどこかでネイティブ関数を呼び出します。
- 使用
- 走る
flutter run
ネイティブ関数が呼び出されることを確認します。 - 走る
flutter build macos
自己完結型リリースを構築するには アプリのバージョン。