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);
}

功能说明

  1. 基本数据类型传递:示例展示了如何在Rust和Dart之间传递基本数据类型(i32)
  2. 函数调用:Dart调用Rust函数(rust_add_numbers)
  3. 回调机制:Rust调用Dart回调函数
  4. 内存管理:正确处理回调资源的创建和释放

注意事项

  1. 确保在构建Rust库时使用正确的目标平台
  2. Dart部分需要正确配置FFI和动态库路径
  3. 跨平台使用时需要注意不同操作系统的动态库扩展名(.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项目示例:

  1. 首先创建Flutter项目:
flutter create rust_flutter_demo
cd rust_flutter_demo
  1. 在项目根目录下创建Rust库:
cargo new --lib native
cd native
  1. 编辑native/Cargo.toml:
[package]
name = "native"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
irondash_dart_ffi = "0.1"
  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()
}
  1. 编辑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
  1. 编辑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'),
            ],
          ),
        ),
      ),
    );
  }
}

平台特定注意事项

  1. Android:需要在build.gradle中启用CMake支持
  2. iOS:需要在Podfile中添加Rust库的引用
  3. 桌面平台:需要确保动态库在正确的位置

性能建议

  1. 对于频繁调用的函数,考虑使用批处理
  2. 大块数据传输使用字节缓冲区而非单独传递
  3. 复杂计算尽量在Rust端完成

irondash_dart_ffi为Rust和Dart之间的互操作提供了高效、类型安全的解决方案,特别适合需要在Flutter应用中集成高性能Rust代码的场景。

回到顶部