Rust跨平台消息通道库irondash_message_channel的使用,实现高效安全的进程间通信
Rust跨平台消息通道库irondash_message_channel的使用,实现高效安全的进程间通信
完整示例demo
Dart端完整代码
import 'dart:ffi';
import 'package:flutter/services.dart';
import 'package:irondash_message_channel/irondash_message_channel.dart';
void main() async {
// 初始化消息通道
final nativeContext = _initNativeContext();
final channel = NativeMethodChannel('demo_channel', context: nativeContext);
// 设置消息处理器
_setupMessageHandlers(channel);
// 调用Rust方法
final version = await channel.invokeMethod('getVersion');
print('Received from Rust: $version');
final sum = await channel.invokeMethod('calculateSum', [5, 7]);
print('Sum from Rust: $sum');
}
// 初始化消息通道上下文
MessageChannelContext _initNativeContext() {
final dylib = DynamicLibrary.process();
final function = dylib.lookup<
NativeFunction<MessageChannelContextInitFunction>>(
"init_message_channel_context");
return MessageChannelContext.forInitFunction(function);
}
// 设置Dart端消息处理器
void _setupMessageHandlers(NativeMethodChannel channel) {
channel.setMethodCallHandler((call) async {
switch (call.method) {
case 'getPlatformInfo':
return 'Dart running on ${Platform.operatingSystem}';
case 'multiplyNumbers':
final args = call.arguments as List;
return args[0] * args[1];
default:
throw PlatformException(
code: 'unimplemented',
message: 'Method ${call.method} not implemented',
);
}
});
}
Rust端完整代码
use irondash_message_channel::*;
use std::os::raw::c_void;
// 初始化函数 - 必须用#[no_mangle]标记且使用extern "C"
#[no_mangle]
pub extern "C" fn init_message_channel_context(data: *mut c_void) -> FunctionResult {
irondash_init_message_channel_context(data)
}
// 主消息处理结构体
struct DemoHandler {
invoker: Late<AsyncMethodInvoker>,
}
#[async_trait(?Send)]
impl AsyncMethodHandler for DemoHandler {
// 设置调用器以便从Rust调用Dart
fn assign_invoker(&self, invoker: AsyncMethodInvoker) {
self.invoker.set(invoker);
}
// 处理来自Dart的方法调用
async fn on_method_call(&self, call: MethodCall) -> PlatformResult {
match call.method.as_str() {
"getVersion" => {
Ok(format!("Rust v{}", env!("CARGO_PKG_VERSION")).into())
}
"calculateSum" => {
let args: Vec<i32> = call.args.try_into()?;
let sum = args[0] + args[1];
Ok(sum.into())
}
_ => Err(PlatformError {
code: "unimplemented".into(),
message: Some(format!("Method {} not implemented", call.method)),
detail: Value::Null,
}),
}
}
}
// 初始化消息通道
pub fn init_message_channel() {
let handler = DemoHandler {
invoker: Late::new(),
}.register("demo_channel");
// 保持handler不被丢弃,否则通道会停止工作
std::mem::forget(handler);
}
// 从Rust调用Dart方法的示例
async fn call_dart_methods(handler: &DemoHandler) {
if let Some(invoker) = handler.invoker.get() {
// 调用Dart端的getPlatformInfo方法
let platform: String = invoker.call_method("getPlatformInfo", Value::Null).await.unwrap().try_into().unwrap();
println!("Dart platform info: {}", platform);
// 调用Dart端的multiplyNumbers方法
let args = vec![3, 4];
let product: i32 = invoker.call_method("multiplyNumbers", args.into()).await.unwrap().try_into().unwrap();
println!("Product from Dart: {}", product);
}
}
使用说明
-
初始化流程:
- Dart端首先加载原生库并初始化消息通道上下文
- Rust端提供初始化函数并通过
register
方法注册处理器
-
双向通信:
- Dart调用Rust通过
invokeMethod
- Rust调用Dart通过
AsyncMethodInvoker
的call_method
- Dart调用Rust通过
-
数据类型:
- 支持基本类型(int, double, String等)
- 支持列表和映射
- 自动序列化/反序列化
-
线程注意事项:
- 确保Rust处理器在具有RunLoop的线程创建
- 跨线程调用需要额外处理
-
错误处理:
- 使用
PlatformError
传递错误信息 - Dart端会收到
PlatformException
- 使用
这个完整示例展示了:
- Dart和Rust的双向方法调用
- 基本数据类型和复杂参数的传递
- 错误处理机制
- 异步通信模式
- 线程安全考虑
使用时需要确保:
- 正确配置Flutter的FFI设置
- Rust库被正确编译为平台特定的动态库
- 在Dart端正确加载原生库
- 保持Rust端的handler不被提前释放
1 回复
Rust跨平台消息通道库irondash_message_channel使用指南
简介
irondash_message_channel是一个Rust实现的跨平台消息通道库,专门设计用于高效安全的进程间通信(IPC)。它提供了简单易用的API,支持多种数据类型传输,并能在不同平台(包括移动端)上工作。
主要特性
- 跨平台支持(Windows, macOS, Linux, iOS, Android)
- 线程安全的通信机制
- 支持多种数据类型传输
- 高性能的二进制序列化
- 简单的错误处理机制
安装
在Cargo.toml中添加依赖:
[dependencies]
irondash_message_channel = "0.3"
基本使用方法
1. 创建消息通道
use irondash_message_channel::{MessageChannel, Value};
fn main() {
// 创建消息通道
let channel = MessageChannel::new("my_channel");
// 设置消息处理器
channel.set_handler(|method: String, args: Value| {
println!("Received method: {}, args: {:?}", method, args);
// 返回响应
Ok(Value::String("Response from Rust".to_string()))
});
}
2. 发送消息
// 发送简单消息
channel.send("greet", Value::String("Hello from Rust".to_string()))
.expect("Failed to send message");
// 发送复杂数据结构
let data = Value::Map(vec![
("name".to_string(), Value::String("Alice".to_string())),
("age".to_string(), Value::I32(30)),
("active".to_string(), Value::Bool(true)),
]);
channel.send("user_data", data).expect("Failed to send user data");
3. 接收和处理消息
channel.set_handler(|method, args| {
match method.as_str() {
"greet" => {
let name = args.as_str().unwrap_or("stranger");
println!("Hello, {}!", name);
Ok(Value::Null)
}
"calculate" => {
let nums = args.as_list().unwrap();
let sum: i64 = nums.iter().map(|v| v.as_i64().unwrap_or(0)).sum();
Ok(Value::I64(sum))
}
_ => {
Err(format!("Unknown method: {}", method).into())
}
}
});
高级用法
1. 异步消息处理
use tokio::runtime::Runtime;
channel.set_async_handler(|method, args| {
Box::pin(async move {
match method.as_str() {
"async_op" => {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
Ok(Value::String("Async operation completed".to_string()))
}
_ => Err("Unknown method".into()),
}
})
});
2. 二进制数据传输
// 发送二进制数据
let binary_data = vec![0x01, 0x02, 0x03, 0x04];
channel.send("binary_data", Value::Binary(binary_data))
.expect("Failed to send binary data");
// 接收二进制数据
channel.set_handler(|method, args| {
if method == "process_binary" {
let data = args.as_binary().unwrap();
println!("Received binary data of length: {}", data.len());
Ok(Value::Null)
} else {
Err("Unknown method".into())
}
});
3. 跨平台集成示例
与Flutter集成的示例:
// Flutter端代码
final channel = MessageChannel('my_channel');
// 发送消息到Rust
final response = await channel.send('greet', 'Hello from Flutter');
print('Response from Rust: $response');
// 接收来自Rust的消息
channel.setMessageHandler((method, args) async {
print('Received from Rust - Method: $method, Args: $args');
return 'Response from Flutter';
});
错误处理
channel.set_handler(|method, args| {
if method == "dangerous_op" {
if some_condition {
Ok(Value::Null)
} else {
Err("Operation failed".into())
}
} else {
Err(format!("Unknown method: {}", method).into())
}
});
// 发送消息时处理错误
match channel.send("dangerous_op", Value::Null) {
Ok(response) => println!("Operation succeeded: {:?}", response),
Err(e) => println!("Operation failed: {}", e),
}
性能优化建议
- 对于高频小消息,考虑批量发送
- 大二进制数据使用
Value::Binary
而不是base64编码的字符串 - 复杂数据结构优先使用
Value::Map
和Value::List
组合 - 异步处理耗时操作以避免阻塞
注意事项
- 消息通道名称在应用中必须唯一
- 跨平台使用时确保两端数据类型兼容
- 大消息可能影响性能,考虑分片传输
- 错误消息应尽量简洁,避免传输敏感信息
完整示例Demo
下面是一个完整的Rust与Flutter跨平台通信示例:
Rust端代码
use irondash_message_channel::{MessageChannel, Value};
use tokio::runtime::Runtime;
fn main() {
// 创建Tokio运行时
let rt = Runtime::new().unwrap();
// 在Tokio运行时中执行
rt.block_on(async {
// 创建消息通道
let channel = MessageChannel::new("app_channel");
// 设置同步消息处理器
channel.set_handler(|method, args| {
match method.as_str() {
"sync_greet" => {
let name = args.as_str().unwrap_or("world");
println!("[Rust] Received sync greeting for: {}", name);
Ok(Value::String(format!("Hello, {} from Rust!", name)))
}
"calculate_sum" => {
let nums = args.as_list().unwrap();
let sum: i64 = nums.iter().map(|v| v.as_i64().unwrap_or(0)).sum();
Ok(Value::I64(sum))
}
_ => Err("Unknown method".into())
}
});
// 设置异步消息处理器
channel.set_async_handler(|method, args| {
Box::pin(async move {
match method.as_str() {
"async_task" => {
let duration = args.as_i64().unwrap_or(1) as u64;
tokio::time::sleep(std::time::Duration::from_secs(duration)).await;
Ok(Value::String("Async task completed".to_string()))
}
_ => Err("Unknown async method".into())
}
})
});
// 发送初始化消息到Flutter
channel.send("init", Value::String("Rust backend ready".to_string()))
.expect("Failed to send init message");
// 保持程序运行
loop {
tokio::time::sleep(std::time::Duration::from_secs(60)).await;
}
});
}
Flutter端代码
import 'package:flutter/material.dart';
import 'package:irondash_message_channel/irondash_message_channel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final channel = MessageChannel('app_channel');
String _response = '';
String _asyncResponse = '';
@override
void initState() {
super.initState();
// 设置消息处理器
channel.setMessageHandler((method, args) async {
print('Received from Rust - Method: $method, Args: $args');
if (method == 'init') {
setState(() {
_response = args;
});
}
return 'Received in Flutter';
});
}
Future<void> _sendMessage() async {
final response = await channel.send('sync_greet', 'Flutter User');
setState(() {
_response = response.toString();
});
}
Future<void> _sendAsyncTask() async {
final response = await channel.send('async_task', 2);
setState(() {
_asyncResponse = response.toString();
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Flutter-Rust IPC Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _sendMessage,
child: Text('Send Sync Message'),
),
SizedBox(height: 20),
Text('Sync Response: $_response'),
SizedBox(height: 40),
ElevatedButton(
onPressed: _sendAsyncTask,
child: Text('Send Async Task'),
),
SizedBox(height: 20),
Text('Async Response: $_asyncResponse'),
],
),
),
),
);
}
}
这个完整示例展示了:
- Rust端创建消息通道并设置同步/异步处理器
- Flutter端与Rust的双向通信
- 不同数据类型的传输
- 异步操作处理
- 跨平台通信的基本模式
您可以根据实际需求扩展此示例,添加更多消息类型和处理逻辑。