Rust插件库rinf的使用:高性能Rust与前端交互的桥梁,实现无缝通信与数据交换
Rust插件库rinf的使用:高性能Rust与前端交互的桥梁,实现无缝通信与数据交换
Rinf: Rust in Flutter
Rust用于原生业务逻辑,Flutter用于灵活美观的GUI
Rinf是一个框架,通过使用Flutter作为UI层来创建美观且高性能的跨平台Rust应用程序。只需将此框架添加到您的应用程序项目中,您就可以在Flutter中编写Rust!
文档
访问文档以了解有关使用此框架的所有信息。您还可以探索示例代码。
平台支持
Flutter可用的所有平台都经过测试和支持。具有挑战性的构建设置由该框架自动处理。
- ✅ Linux:测试并支持
- ✅ Android:测试并支持
- ✅ Windows:测试并支持
- ✅ macOS:测试并支持
- ✅ iOS:测试并支持
- ✅ Web:测试并支持
- 🔄 eLinux:目前实验性
通信
以下是带有业务逻辑的Rust代码,随后是带有小部件的Dart代码。
MyMessage {
current_number: 7,
other_bool: true,
}
.send_signal_to_dart();
StreamBuilder(
stream: MyMessage.rustSignalStream,
builder: (context, snapshot) {
final signalPack = snapshot.data;
if (signalPack == null) {
return Text('Nothing received yet');
}
final myMessage = signalPack.message;
return Text(myMessage.currentNumber.toString());
},
)
从Dart到Rust的消息传递也可以以类似的方式进行。
所有Dart类都是由Rinf以类型安全的方式生成的。您可以通过在Rust中使用可派生特征来定义消息模式。
好处
- 真正简单:只需大约一两分钟即可完全设置您的应用程序。
- 高效:所有通信仅通过原生FFI进行。没有Web视图、Web服务器、隐藏线程或不必要的内存复制可能导致性能开销。此设置充当Dart和Rust的非常薄的包装器。
- 最小化:这不是一个笨重的框架,需要您安装许多依赖项并使用复杂的CLI命令。只需专注于使用您喜欢的Flutter和Rust库编写代码。
- 事件驱动:异步系统对用户操作、消息或信号等事件做出反应。这允许高级并发、任务取消和非阻塞业务逻辑。
- 可扩展:在Dart和Rust之间创建数百甚至数千个消息API感觉流畅且干净。此外,您可以灵活地使用任意数量的Rust库crate,可能包括您一直在使用的那些。
- 高级接口:无需处理敏感的构建文件,无需担心内存安全。坚持使用您熟悉的Dart和Rust。
- 维护良好:我们的自动化工作流程(包括构建测试)始终保持通过,这得益于主分支保护规则。此外,外部依赖项的数量尽可能保持较低,并且文档经过精心组织。
- 方便的调试:所有调试功能都默认提供,无需处理浏览器或移动模拟器。此外,整个Rust逻辑在Dart的热重启时自动重新启动。
- 可靠:每个组件都由庞大的社区支持,确保对未来安全的高度重视。您可以轻松地向团队保证稳定性,因为此框架的底层概念相当简单。
为什么使用Flutter?
虽然Rust是一种用于高性能原生编程的强大语言,但其构建图形用户界面的生态系统远未成熟。尽管Rust已经有一些GUI框架,但它们无法与Flutter提供的广泛支持和平滑的开发体验相提并论。Flutter是唯一一个从单一代码库编译到所有六个主要平台的框架。
Flutter是一个强大且多功能的框架,因其构建具有惊人用户界面的跨平台应用程序而广受欢迎。它提供声明式模式、美观的小部件、热重载、方便的调试工具以及开箱即用的专用用户界面包。
为什么使用Rust?
虽然Dart作为一种用于GUI应用程序的出色面向对象语言表现出色,但其非原生垃圾收集可能并不总是满足苛刻的性能要求,并且可能缺乏高级数据操作包。这就是Rust介入的地方,提供高达Dart40倍的速度优势,以及利用多个线程和各种完成工作的crate的能力。
Rust已经赢得了忠实的追随者,成为Stack Overflow上最受喜爱的编程语言。其原生性能,得益于零成本抽象哲学,确保了高生产力。许多开发人员预见Rust可能在未来取代C++。Rust的简单性、内存安全性、在各种场景下的卓越性能、充满活力的社区和强大的工具支持促成了其日益增长的受欢迎程度。
贡献
如果Rinf对您有帮助,请考虑给我们的GitHub存储库一个星标,并给我们的Pub包一个点赞。您还可以通过在网络上传播和分享此框架来支持我们。
我们感谢您对此项目开发的贡献!我们始终开放讨论和拉取请求,因此请不要犹豫,在我们的GitHub存储库上分享您的想法或意见。
完整示例代码:
// Rust端代码示例
use rinf::*;
// 定义消息结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MyMessage {
pub current_number: i32,
pub other_bool: bool,
}
impl Message for MyMessage {
// 实现消息特征
}
// 业务逻辑处理
fn handle_business_logic() {
// 创建消息实例
let message = MyMessage {
current_number: 7,
other_bool: true,
};
// 发送信号到Dart
message.send_signal_to_dart();
}
// 处理从Dart接收的消息
#[rinf::async_trait]
impl MessageHandler for MyMessage {
async fn handle_message(&self) {
// 处理接收到的消息
println!("Received message: {:?}", self);
}
}
// Dart端代码示例
import 'package:flutter/material.dart';
import 'package:rinf/rinf.dart';
// 在Flutter widget中使用
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Rinf Example'),
),
body: StreamBuilder(
stream: MyMessage.rustSignalStream,
builder: (context, snapshot) {
final signalPack = snapshot.data;
if (signalPack == null) {
return Text('Nothing received yet');
}
final myMessage = signalPack.message;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Current Number: ${myMessage.currentNumber}'),
Text('Other Bool: ${myMessage.otherBool}'),
],
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 发送消息到Rust
final message = MyMessage(
currentNumber: 42,
otherBool: false,
);
message.sendSignalToRust();
},
child: Icon(Icons.send),
),
),
);
}
}
Rust插件库rinf:高性能Rust与前端交互的桥梁
介绍
rinf是一个专为Rust开发者设计的高性能插件库,旨在简化Rust与前端(如JavaScript/TypeScript)之间的通信和数据交换。通过提供简洁的API和高效的底层实现,rinf使得在Web应用、桌面应用或移动应用中集成Rust逻辑变得更加容易,同时保持出色的性能。
主要特性
- 高性能通信:利用高效的序列化和反序列化机制,确保低延迟的数据交换
- 跨平台支持:兼容多种前端框架和运行时环境(如WebAssembly、Node.js等)
- 类型安全:通过Rust的强类型系统,减少运行时错误
- 异步支持:原生支持异步操作,适合高并发场景
使用方法
安装
在Cargo.toml
中添加依赖:
[dependencies]
rinf = "0.5"
基本示例
以下是一个简单的示例,展示如何在Rust中定义函数,并通过rinf暴露给前端调用。
- 在Rust中定义函数:
use rinf::prelude::*;
// 定义一个简单的加法函数
#[rinf::bridge]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// 定义一个异步函数,模拟耗时操作
#[rinf::bridge]
pub async fn fetch_data(url: String) -> Result<String, String> {
// 模拟网络请求
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
Ok(format!("Data from {}", url))
}
- 在前端(JavaScript)中调用:
// 假设rinf前端库已导入
import { callRust } from 'rinf-js';
// 调用同步函数
const result = await callRust('add', [5, 3]);
console.log(result); // 输出: 8
// 调用异步函数
try {
const data = await callRust('fetch_data', ['https://example.com']);
console.log(data); // 输出: "Data from https://example.com"
} catch (error) {
console.error(error);
}
高级用法:复杂数据交换
rinf支持结构体和枚举类型的传递,确保类型安全。
- 在Rust中定义数据结构:
use rinf::prelude::*;
#[rinf::bridge]
#[derive(Serialize, Deserialize)]
pub struct User {
id: u64,
name: String,
email: String,
}
#[rinf::bridge]
pub fn create_user(name: String, email: String) -> User {
User {
id: 1, // 模拟ID生成
name,
email,
}
}
- 在前端中调用:
// 创建用户
const user = await callRust('create_user', ['Alice', 'alice@example.com']);
console.log(user); // 输出: { id: 1, name: "Alice", email: "alice@example.com" }
错误处理
rinf支持Result类型,方便错误传递。
#[rinf::bridge]
pub fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
在前端中处理错误:
try {
const result = await callRust('divide', [10, 2]);
console.log(result); // 输出: 5
} catch (error) {
console.error(error); // 如果除零错误,输出: "Division by zero"
}
完整示例demo
Rust后端代码 (src/lib.rs)
use rinf::prelude::*;
use serde::{Deserialize, Serialize};
// 基本数学运算函数
#[rinf::bridge]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[rinf::bridge]
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
#[rinf::bridge]
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
#[rinf::bridge]
pub fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
// 异步数据获取函数
#[rinf::bridge]
pub async fn fetch_data(url: String) -> Result<String, String> {
// 模拟网络请求延迟
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
if url.contains("example") {
Ok(format!("Fetched data from {}", url))
} else {
Err("Invalid URL".to_string())
}
}
// 用户管理相关数据结构和函数
#[rinf::bridge]
#[derive(Serialize, Deserialize, Debug)]
pub struct User {
pub id: u64,
pub name: String,
pub email: String,
pub age: u8,
}
#[rinf::bridge]
#[derive(Serialize, Deserialize, Debug)]
pub enum UserStatus {
Active,
Inactive,
Suspended,
}
#[rinf::bridge]
pub fn create_user(name: String, email: String, age: u8) -> User {
User {
id: generate_id(),
name,
email,
age,
}
}
#[rinf::bridge]
pub fn get_user_status(user: User) -> UserStatus {
if user.age >= 18 {
UserStatus::Active
} else {
UserStatus::Inactive
}
}
// 工具函数
fn generate_id() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
let start = SystemTime::now();
let since_epoch = start.duration_since(UNIX_EPOCH).unwrap();
since_epoch.as_secs()
}
// 批量处理函数
#[rinf::bridge]
pub fn process_numbers(numbers: Vec<i32>) -> Vec<i32> {
numbers.into_iter().map(|x| x * 2).collect()
}
#[rinf::bridge]
pub async fn batch_process_urls(urls: Vec<String>) -> Vec<Result<String, String>> {
let mut results = Vec::new();
for url in urls {
// 模拟每个URL的处理
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
if url.starts_with("https://") {
results.push(Ok(format!("Processed: {}", url)));
} else {
results.push(Err(format!("Invalid URL: {}", url)));
}
}
results
}
前端JavaScript代码 (main.js)
import { callRust } from 'rinf-js';
// 数学运算示例
async function mathOperations() {
try {
console.log('=== 数学运算演示 ===');
// 加法
const sum = await callRust('add', [10, 5]);
console.log('10 + 5 =', sum);
// 减法
const difference = await callRust('subtract', [20, 8]);
console.log('20 - 8 =', difference);
// 乘法
const product = await callRust('multiply', [6, 7]);
console.log('6 × 7 =', product);
// 除法 - 正常情况
const quotient = await callRust('divide', [15, 3]);
console.log('15 ÷ 3 =', quotient);
// 除法 - 错误情况
try {
await callRust('divide', [10, 0]);
} catch (error) {
console.log('10 ÷ 0 错误:', error);
}
} catch (error) {
console.error('数学运算错误:', error);
}
}
// 异步数据获取示例
async function dataFetching() {
try {
console.log('\n=== 数据获取演示 ===');
// 成功的数据获取
const data1 = await callRust('fetch_data', ['https://example.com/api']);
console.log('数据获取成功:', data1);
// 失败的数据获取
try {
await callRust('fetch_data', ['invalid-url']);
} catch (error) {
console.log('数据获取失败:', error);
}
} catch (error) {
console.error('数据获取演示错误:', error);
}
}
// 用户管理示例
async function userManagement() {
try {
console.log('\n=== 用户管理演示 ===');
// 创建用户
const user = await callRust('create_user', ['张三', 'zhangsan@example.com', 25]);
console.log('创建的用户:', user);
// 获取用户状态
const status = await callRust('get_user_status', [user]);
console.log('用户状态:', status);
// 创建未成年用户
const minorUser = await callRust('create_user', ['李四', 'lisi@example.com', 16]);
const minorStatus = await callRust('get_user_status', [minorUser]);
console.log('未成年用户状态:', minorStatus);
} catch (error) {
console.error('用户管理错误:', error);
}
}
// 批量处理示例
async function batchProcessing() {
try {
console.log('\n=== 批量处理演示 ===');
// 数字批量处理
const numbers = [1, 2, 3, 4, 5];
const processedNumbers = await callRust('process_numbers', [numbers]);
console.log('原始数字:', numbers);
console.log('处理后的数字:', processedNumbers);
// URL批量处理
const urls = [
'https://api1.example.com',
'https://api2.example.com',
'invalid-url',
'https://api3.example.com'
];
console.log('开始批量处理URLs...');
const urlResults = await callRust('batch_process_urls', [urls]);
console.log('URL处理结果:');
urlResults.forEach((result, index) => {
if (result.ok) {
console.log(` ${urls[index]}: 成功 -`, result.value);
} else {
console.log(` ${urls[index]}: 失败 -`, result.error);
}
});
} catch (error) {
console.error('批量处理错误:', error);
}
}
// 主执行函数
async function main() {
console.log('开始Rust与前端交互演示...\n');
await mathOperations();
await dataFetching();
await userManagement();
await batchProcessing();
console.log('\n=== 演示完成 ===');
}
// 执行主函数
main().catch(console.error);
前端HTML模板 (index.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rinf演示应用</title>
<script type="module" src="./main.js"></script>
</head>
<body>
<h1>Rinf Rust与前端交互演示</h1>
<p>打开浏览器控制台查看演示结果</p>
</body>
</html>
Cargo.toml配置
[package]
name = "rinf-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
rinf = "0.5"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
[lib]
crate-type = ["cdylib"]
总结
rinf通过简洁的API和高效的实现,为Rust与前端之间的通信提供了强大支持。无论是简单的函数调用还是复杂的数据交换,rinf都能确保类型安全和性能优化。通过上述完整示例,您可以快速开始使用rinf构建高性能的跨平台应用。