Flutter x Rust
flutter_rust_bridge_codegen v1 のときの記述です。V1は個人的に非推奨
個人的にプログラミング言語の中では好きな部類である2つの言語を良い感じに融合します。
具体的には Flutter 側から Rust のコードを呼び出すようにします。
前提として Flutter から Rust のコードを呼び出すには多少のオーバーヘッドがあり、
軽い処理を行う Rust コードを何度も呼び出すようなことは逆に重くなるだけなので、Flutter(dart)側で処理したほうが良いでしょう。
環境
Windows 11
Flutter, Rust がインストールされている
事前準備
$ winget install -e --id LLVM.LLVM
$ cargo install flutter_rust_bridge_codegen
プロジェクトを作る
$ flutter create app
$ cd app
$ cargo new --lib native
Rust プロジェクト(native (名前は任意)以下の Cargo.toml に)以下を追記
code:Cargo.toml
flutter_rust_bridge = "1"
Flutter プロジェクトの pubspec.yaml に以下を追加
code: pubspec.yaml
dependencies:
freezed_annotation: ^2.4.1
ffi: ^2.1.0
meta: ^1.9.1
flutter_rust_bridge: ^1.81.0
dev_dependencies:
build_runner: ^2.4.6
ffigen: ^8.0.2
source_gen: ^1.4.0
freezed: ^2.4.2
※ここでバージョンに注意する
$ flutter_rust_bridge_codegen --version
flutter_rust_bridge_codegen のバージョンと flutter の flutter_rust_bridge のバージョンは同じようにしておく必要があるようです。
flutter_rust_bridge: ^1.44.0 と flutter_rust_bridge_codegen@1.81.0 を使用すると問題が発生しました。
恐らく破壊的な変更があったのでしょう......
flutter pub add で追加した場合、自動で依存性を解決するためのバージョンがインストールされますが、flutter_rust_bridge のバージョンに flutter_rust_bridge_codegen のバージョンを合わせるほうが良いでしょう。
$ cargo install flutter_rust_bridge_codegen@1.44.0
のようにしてバージョンを変更すると良いでしょう。
問題を解決するまで 1 時間はかかりました(一敗)
Rust のコードを記述する
code: native/src/api.rs
// Flutter側に公開する関数はapi.rsに定義する
pub fn greet() -> String {
"Hello from Rust!".into()
}
code: native/src/lib.rs
mod api;
今回は単純に文字列を返すだけの greet 関数を定義し、api.rs に記述します。(api.rs でなくても後で行うファイル指定を変更すれば良いだけです)
Flutter のコードを記述する
code:lib/bridge/ffi.dart
import 'dart:ffi';
import 'dart:io' as io;
import 'bridge_definitions.dart';
import 'bridge_generated.dart';
export 'bridge_definitions.dart';
export 'bridge_generated.dart';
const _base = 'native';
final _dylib = io.Platform.isWindows ? '$_base.dll' : 'lib$_base.so';
final Native api = NativeImpl(io.Platform.isIOS || io.Platform.isMacOS
? DynamicLibrary.executable()
: DynamicLibrary.open(_dylib));
lib/bridge に ffi.dart を作成し、記述します。
必要なコードを生成する
$ flutter_rust_bridge_codegen --rust-input native/src/api.rs --dart-output lib/bridge/bridge_generated.dart --dart-decl-output lib/bridge/bridge_definitions.dart
を実行
以下のファイルが生成されていればOKです。
lib/bridge/bridge_generated.dart
lib/bridge/bridge_definitions.dart
native/src/bridge_generated.io.rs
native/src/bridge_generated.rs
Flutter から Rust 関数を呼び出す
呼び出すコードは以下のようになります。任意の場所に記述してください。
code:main.dart
final x = await api.greet();
print(x);
Windows で flutter を実行する
2024-03-24追記 ※上記リンクが無効になっています。最新のものを調査して書き直すかもしれません。
windows/rust.cmake ファイルを作成し、以下を記述します。
code:windows/rust.cmake
# We include Corrosion inline here, but ideally in a project with
# many dependencies we would need to install Corrosion on the system.
# Once done, uncomment this line:
# find_package(Corrosion REQUIRED)
include(FetchContent)
FetchContent_Declare(
Corrosion
GIT_TAG origin/master # Optionally specify a version tag or branch here
)
FetchContent_MakeAvailable(Corrosion)
corrosion_import_crate(MANIFEST_PATH ../native/Cargo.toml IMPORTED_CRATES imported_crates)
target_link_libraries(${BINARY_NAME} PRIVATE ${imported_crates})
foreach(imported_crate ${imported_crates})
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${imported_crate}-shared>)
endforeach()
windows/CMakeLists.txt に include(./rust.cmake) を追記する。
code:windows/CMakeLists.txt
......
# them to the application.
include(flutter/generated_plugins.cmake)
# ここに以下の行を追加する
include(./rust.cmake)
# === Installation ===
# Support files are copied into place next to the executable, so that it can
......
あとはいつものように device を windows にして実行するだけです。
windows 実行は開発者モードをオンにしていないと実行できないので注意。
疲れました