Rust跨平台FFI库irondash_dart_ffi的使用:实现Rust与Dart的高效互操作
Rust跨平台FFI库irondash_dart_ffi的使用:实现Rust与Dart的高效互操作
安装
在项目目录中运行以下Cargo命令:
cargo add irondash_dart_ffi
或在Cargo.toml中添加以下行:
irondash_dart_ffi = "0.2.0"
示例Demo
下面是一个完整的Rust与Dart互操作示例:
Rust部分
use irondash_dart_ffi::{DartFunction, DartHandle};
// 定义一个Rust函数,可以被Dart调用
#[no_mangle]
pub extern "C" fn rust_add_numbers(a: i32, b: i32) -> i32 {
a + b
}
// 定义一个结构体来管理Dart回调
pub struct DartCallback {
callback: DartFunction,
}
impl DartCallback {
pub fn new(callback: DartFunction) -> Self {
Self { callback }
}
// 调用Dart回调
pub fn call(&self, value: i32) {
self.callback.invoke1(value).unwrap();
}
}
// 注册Dart回调
#[no_mangle]
pub extern "C" fn register_dart_callback(callback: DartFunction) -> *mut DartCallback {
Box::into_raw(Box::new(DartCallback::new(callback)))
}
// 释放Dart回调
#[no_mangle]
pub extern "C" fn free_dart_callback(ptr: *mut DartCallback) {
unsafe {
if !ptr.is_null() {
Box::from_raw(ptr);
}
}
}
Dart部分
import 'dart:ffi';
import 'package:ffi/ffi.dart';
// 定义Dart与Rust的FFI接口
typedef RustAddNumbers = Int32 Function(Int32 a, Int32 b);
typedef RegisterDartCallback = Pointer<Void> Function(Pointer<Void> callback);
typedef FreeDartCallback = Void Function(Pointer<Void> callback);
// Dart回调函数类型
typedef DartCallback = Void Function(Int32 value);
void main() {
final lib = DynamicLibrary.open('path/to/your/rust/library.so');
final addNumbers = lib.lookupFunction<RustAddNumbers, RustAddNumbers>('rust_add_numbers');
final registerCallback = lib.lookupFunction<RegisterDartCallback, RegisterDartCallback>('register_dart_callback');
final freeCallback = lib.lookupFunction<FreeDartCallback, FreeDartCallback>('free_dart_callback');
// 调用Rust函数
final result = addNumbers(5, 7);
print('Result from Rust: $result'); // 输出: Result from Rust: 12
// 创建Dart回调
final callback = Pointer.fromFunction<DartCallback>(_dartCallback);
// 注册回调到Rust
final callbackHandle = registerCallback(callback);
// 在Rust中会调用这个回调
void _dartCallback(int value) {
print('Received from Rust: $value');
}
// 清理
freeCallback(callbackHandle);
}
功能说明
- 基本数据类型传递:示例展示了如何在Rust和Dart之间传递基本数据类型(i32)
- 函数调用:Dart调用Rust函数(
rust_add_numbers
) - 回调机制:Rust调用Dart回调函数
- 内存管理:正确处理回调资源的创建和释放
注意事项
- 确保在构建Rust库时使用正确的目标平台
- Dart部分需要正确配置FFI和动态库路径
- 跨平台使用时需要注意不同操作系统的动态库扩展名(.so/.dll/.dylib)
这个示例展示了irondash_dart_ffi库的核心功能,包括双向函数调用和回调机制,适合作为Rust与Dart互操作的起点。
更多关于Rust跨平台FFI库irondash_dart_ffi的使用:实现Rust与Dart的高效互操作的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Rust跨平台FFI库irondash_dart_ffi的使用:实现Rust与Dart的高效互操作的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
Rust跨平台FFI库irondash_dart_ffi的使用:实现Rust与Dart的高效互操作
介绍
irondash_dart_ffi是一个用于Rust和Dart之间高效互操作的FFI(外部函数接口)库。它专门为Flutter应用设计,允许开发者将高性能的Rust代码集成到Dart/Flutter应用中,同时保持跨平台兼容性。
主要特点:
- 支持Android、iOS、Linux、Windows和macOS平台
- 提供类型安全的绑定生成
- 支持异步操作
- 内存管理自动化
- 线程安全设计
使用方法
1. 添加依赖
在Cargo.toml中添加:
[dependencies]
irondash_dart_ffi = "0.1"
在pubspec.yaml中添加:
dependencies:
irondash_dart_ffi: ^0.1.0
2. 基本示例
Rust端代码 (lib.rs)
use irondash_dart_ffi::{IntoDart, DartValue};
// 导出给Dart调用的简单加法函数
#[no_mangle]
pub extern "C" fn add_numbers(a: i32, b: i32) -> i32 {
a + b
}
// 导出给Dart调用的字符串处理函数
#[no_mangle]
pub extern "C" fn greet(name: &str) -> DartValue {
format!("Hello, {}!", name).into_dart()
}
Dart端代码
import 'package:irondash_dart_ffi/irondash_dart_ffi.dart';
// 加载Rust库
final rustLib = NativeLibrary.load();
void main() {
// 调用Rust函数
final sum = rustLib.add_numbers(5, 7);
print('Sum: $sum'); // 输出: Sum: 12
final greeting = rustLib.greet('Rust');
print(greeting); // 输出: Hello, Rust!
}
3. 复杂类型处理
Rust端
use irondash_dart_ffi::{IntoDart, FromDart, DartValue};
// 定义一个可以在Rust和Dart之间传递的结构体
#[derive(FromDart, IntoDart)]
struct Person {
name: String,
age: i32,
}
// 创建Person对象的函数
#[no_mangle]
pub extern "C" fn create_person(name: String, age: i32) -> DartValue {
Person { name, age }.into_dart()
}
// 修改Person对象的函数
#[no_mangle]
pub extern "C" fn celebrate_birthday(person: Person) -> DartValue {
Person {
name: person.name,
age: person.age + 1,
}.into_dart()
}
Dart端
final person = rustLib.create_person('Alice', 30);
print('Original: ${person.name}, ${person.age}');
final olderPerson = rustLib.celebrate_birthday(person);
print('After birthday: ${olderPerson.name}, ${olderPerson.age}');
4. 异步操作
Rust端
use std::thread;
use std::time::Duration;
use irondash_dart_ffi::{AsyncTask, IntoDart};
// 模拟长时间运行的任务
#[no_mangle]
pub extern "C" fn long_running_task(input: String) -> AsyncTask<String> {
AsyncTask::spawn(move || {
thread::sleep(Duration::from_secs(2));
format!("Processed: {}", input.to_uppercase())
})
}
Dart端
final task = rustLib.long_running_task('hello world');
task.then((result) {
print(result); // 2秒后输出: Processed: HELLO WORLD
});
高级用法
回调函数
Rust端
use irondash_dart_ffi::{DartFn, IntoDart};
// 使用Dart回调函数的示例
#[no_mangle]
pub extern "C" fn process_with_callback(data: i32, callback: DartFn<i32, String>) -> DartValue {
let result = if data > 0 {
callback.call(data * 2).unwrap_or_else(|_| "Error".to_string())
} else {
"Invalid input".to_string()
};
result.into_dart()
}
Dart端
String doubleToString(int value) => 'Double: ${value * 2}';
final result = rustLib.process_with_callback(5, doubleToString);
print(result); // 输出: Double: 20
完整示例demo
以下是一个完整的Flutter+Rust项目示例:
- 首先创建Flutter项目:
flutter create rust_flutter_demo
cd rust_flutter_demo
- 在项目根目录下创建Rust库:
cargo new --lib native
cd native
- 编辑native/Cargo.toml:
[package]
name = "native"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
irondash_dart_ffi = "0.1"
- 编辑native/src/lib.rs:
use irondash_dart_ffi::{IntoDart, FromDart, DartValue, AsyncTask, DartFn};
use std::thread;
use std::time::Duration;
// 简单数学运算
#[no_mangle]
pub extern "C" fn add_numbers(a: i32, b: i32) -> i32 {
a + b
}
// 字符串处理
#[no_mangle]
pub extern "C" fn greet(name: &str) -> DartValue {
format!("Hello, {}!", name).into_dart()
}
// 结构体示例
#[derive(FromDart, IntoDart)]
struct User {
id: i64,
username: String,
is_active: bool,
}
#[no_mangle]
pub extern "C" fn create_user(id: i64, username: String) -> DartValue {
User {
id,
username,
is_active: true,
}.into_dart()
}
// 异步任务
#[no_mangle]
pub extern "C" fn fetch_data_async(url: String) -> AsyncTask<String> {
AsyncTask::spawn(move || {
thread::sleep(Duration::from_secs(1));
format!("Fetched data from {}", url)
})
}
// 回调函数
#[no_mangle]
pub extern "C" fn process_with_callback(value: i32, callback: DartFn<i32, String>) -> DartValue {
let result = callback.call(value * 3).unwrap_or_else(|_| "Callback failed".to_string());
result.into_dart()
}
- 编辑Flutter项目的pubspec.yaml:
dependencies:
flutter:
sdk: flutter
irondash_dart_ffi: ^0.1.0
flutter:
plugin:
platforms:
android:
package: com.example.rust_flutter_demo
pluginClass: RustFlutterDemoPlugin
ios:
pluginClass: RustFlutterDemoPlugin
linux:
pluginClass: RustFlutterDemoPlugin
macos:
pluginClass: RustFlutterDemoPlugin
windows:
pluginClass: RustFlutterDemoPlugin
- 编辑lib/main.dart:
import 'package:flutter/material.dart';
import 'package:irondash_dart_ffi/irondash_dart_ffi.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final rustLib = NativeLibrary.load();
String tripleCallback(int value) => 'Tripled: ${value * 3}';
@override
Widget build(BuildContext context) {
// 调用各种Rust函数
final sum = rustLib.add_numbers(10, 20);
final greeting = rustLib.greet('Flutter');
final user = rustLib.create_user(1, 'rustfan');
rustLib.fetch_data_async('https://example.com').then((result) {
print(result);
});
final callbackResult = rustLib.process_with_callback(5, tripleCallback);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Rust + Flutter Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Sum: $sum'),
Text('Greeting: $greeting'),
Text('User: ${user.username}, ID: ${user.id}'),
Text('Callback result: $callbackResult'),
],
),
),
),
);
}
}
平台特定注意事项
- Android:需要在build.gradle中启用CMake支持
- iOS:需要在Podfile中添加Rust库的引用
- 桌面平台:需要确保动态库在正确的位置
性能建议
- 对于频繁调用的函数,考虑使用批处理
- 大块数据传输使用字节缓冲区而非单独传递
- 复杂计算尽量在Rust端完成
irondash_dart_ffi为Rust和Dart之间的互操作提供了高效、类型安全的解决方案,特别适合需要在Flutter应用中集成高性能Rust代码的场景。