mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
279 lines
13 KiB
Markdown
279 lines
13 KiB
Markdown
# Rust 在移动端可以做什么
|
||
|
||
> uniffi 的思路,和早期类似营销计算的逻辑用 ts 写好,端上 js 引擎加速,Android、iOS 再去使用是一个思路。
|
||
|
||
## 一、Uniffi 在移动端能做什么?
|
||
|
||
### 1. uniffi 是什么?
|
||
|
||
uniffi(全称 “Uniffi-rs”)是 Mozilla 开发的一个跨语言绑定生成工具,核心作用是让 Rust 代码能被其他编程语言(如 Swift、Kotlin、Python、JavaScript 等)无缝调用,通过自动生成类型安全的绑定层,大幅简化跨语言 FFI(Foreign Function Interface)开发的复杂度。
|
||
|
||
### 2. 为什么营销计算的逻辑适合用 ts 写?
|
||
|
||
纯函数,给定恒定的输入,输出不变。这非常适合 ts、rust 去实现。所以可以说,纯函数、纯逻辑适合用 Rust 去开发。区别在于即使采用类似 Wasm、JS 引擎预热、预加载等技术手段,Rust 天然比 JS 效率高。
|
||
|
||
### 3. ffi 能做什么?
|
||
|
||
早期 Flutter 和 Native 交互走 method channel 效率低,所以腾讯的同学开发了 Dart Native 方案,就是基于 ffi 的思路。
|
||
|
||
|
||
所以可以回答 Uniffi 能做什么的问题了:
|
||
|
||
uniffi 的核心是 “让 Rust 成为跨语言共享逻辑的‘通用语言’”,尤其在移动端,它解决了 iOS 和 Android 逻辑重复开发的问题,同时借助 Rust 的安全和性能优势,提升核心模块的可靠性。它更适合 “业务逻辑层” 而非 “UI 层”(UI 仍需依赖各平台原生框架),是移动端跨平台开发的重要补充工具
|
||
|
||
|
||
|
||
uniffi 的核心价值是跨语言复用 Rust 代码,因此它适合开发 “需要在多平台 / 多语言间共享的核心逻辑”,尤其适合以下场景:
|
||
|
||
1. 跨平台共享的业务逻辑当同一套逻辑需要在多个平台(如移动端 iOS/Android、桌面端、后端服务)实现时,用 Rust 编写一次核心逻辑,再通过 uniffi 生成各平台对应的绑定(如 Swift 绑定供 iOS 调用,Kotlin 绑定供 Android 调用、桌面端 Electron js 去调用、小程序 js 去调用),避免重复开发,保证逻辑一致性。
|
||
2. 对安全性、性能要求高的模块 Rust 自带内存安全和零成本抽象特性,适合处理敏感逻辑(如加密解密、用户认证、支付流程)或性能敏感操作(如数据解析、复杂计算、实时处理)。uniffi 能让这些 Rust 模块被其他语言(如动态语言)安全调用,兼顾安全性与开发效率。
|
||
3. 需要跨语言交互的中间层例如,在一个混合技术栈的项目中(如前端用 JavaScript、后端用 Python、移动端用 Kotlin/Swift),可以用 Rust 编写通用的数据处理或协议解析逻辑,再通过 uniffi 生成多语言绑定,作为各层之间的 “桥梁”。
|
||
4. 替代手动 FFI 开发传统跨语言调用需要手动编写 FFI 绑定(如用 extern "C" 暴露 Rust 接口,再在其他语言中手动适配类型),容易出错且维护成本高。uniffi 可自动生成类型安全的绑定,大幅降低开发和维护成本。
|
||
|
||
## 二、移动端中 uniffi 可以做什么?
|
||
|
||
移动端开发的核心痛点之一是 “iOS(Swift/Objective-C)和 Android(Kotlin/Java)需要重复实现相同逻辑”,而 uniffi 恰好能通过 Rust 实现跨平台逻辑复用,具体应用场景包括:共享核心业务逻辑例如:用户登录流程、权限验证、数据校验规则、业务状态管理等。用 Rust 编写一次,通过 uniffi 生成 Swift 绑定(供 iOS)和 Kotlin 绑定(供 Android),两端直接调用,避免 “同一逻辑两套代码” 的冗余和不一致问题。
|
||
|
||
高性能数据处理移动端涉及的复杂数据处理(如 JSON/Protobuf 解析、大数据集合过滤 / 排序、二进制协议编解码),用 Rust 实现可获得比 Kotlin/Swift 更高的性能,uniffi 可让两端高效调用这些逻辑。
|
||
|
||
安全敏感操作如加密(AES、RSA)、解密、签名验证、敏感数据(密码、Token)存储逻辑等,Rust 的内存安全特性可减少传统 C/C++ 调用可能带来的内存漏洞风险,uniffi 则确保调用过程的类型安全。
|
||
|
||
跨平台工具类例如:日期时间处理、字符串工具、设备信息计算(如唯一标识生成)等通用工具,用 Rust 实现后,通过 uniffi 让 iOS 和 Android 共享,减少重复开发。
|
||
|
||
与现有跨平台框架配合即使项目使用 Flutter、React Native 等跨平台 UI 框架,也可通过 uniffi 将 Rust 逻辑作为 “原生能力扩展”:例如 Flutter 中通过 Platform Channel 调用 uniffi 生成的 Rust 绑定,处理 Flutter 难以高效实现的复杂计算。
|
||
|
||
|
||
|
||
### 三、Rust 中使用 Unifii 实现与 Swift 高效互操作性
|
||
UniFFI(Universal Foreign Function Interface)是一个工具集,旨在帮助开发者轻松生成适用于多个编程语言(如 Swift、Kotlin 和 Python)的外部函数接口 (FFI) 绑定。它允许你通过定义一个接口描述语言 (UDL) 文件,自动生成跨语言的绑定代码,从而简化 Rust 代码与其他语言之间的交互。
|
||
|
||
#### 1. 必要工具
|
||
开始之前,你需要确保已经安装了以下工具:
|
||
- Rust 和 Cargo:Rust 是一种系统编程语言,强调安全性和性能。Cargo 是 Rust 的包管理器和构建系统。
|
||
验证安装:运行以下命令确保 Rust 和 Cargo 已正确安装。
|
||
```shell
|
||
rustc --version
|
||
cargo --version
|
||
```
|
||
- UniFFI CLI 工具:UniFFI 提供了一个命令行工具,用于生成绑定代码。安装 UniFFI:你可以通过 Cargo 安装 UniFFI。
|
||
```shell
|
||
cargo install uniffi_bindgen
|
||
```
|
||
验证安装:运行以下命令确保 UniFFI 已正确安装。
|
||
```shell
|
||
uniffi-bindgen --version
|
||
```
|
||
|
||
#### 2. 项目设置
|
||
1. 创建 Rust 项目
|
||
- 打开终端并运行以下命令创建一个新的 Rust 库项目:
|
||
```shell
|
||
cargo new my_rust_library --lib
|
||
cd my_rust_library
|
||
```
|
||
- 编辑Cargo.toml文件,添加 Uniffi 依赖项
|
||
```shell
|
||
[dependencies]
|
||
uniffi = "0.27.0"
|
||
serde = { version = "1.0", features = ["derive"] }
|
||
```
|
||
- 配置Cargo.toml文件中的lib部分,设置 crate 类型为 cdylib:
|
||
```shell
|
||
[lib]
|
||
crate-type = ["cdylib"]
|
||
```
|
||
|
||
2. 创建名为 `MySwiftApp` 的Swift 项目
|
||
|
||
#### 3. Rust 库的创建
|
||
我们将创建一个简单的 Rust 库,并配置它以便与 Swift 互操作。我们将定义一个数据结构和一些基本的功能,使用 UniFFI 来生成绑定。
|
||
1. 设置 Cargo.toml
|
||
首先,我们需要在 Cargo.toml 文件中配置项目依赖和库类型:
|
||
```rs
|
||
[package]
|
||
name = "my_rust_library"
|
||
version = "0.1.0"
|
||
edition = "2018"
|
||
|
||
[dependencies]
|
||
uniffi = "0.27.0" # 检查最新版本
|
||
serde = { version = "1.0", features = ["derive"] }
|
||
|
||
[lib]
|
||
crate-type = ["cdylib"]
|
||
```
|
||
2. 编写 Rust 代码
|
||
在 src/lib.rs 文件中编写 Rust 代码。我们将定义一个简单的结构体 Greeting 和相关的方法。
|
||
```rs
|
||
// src/lib.rs
|
||
use serde::{Serialize, Deserialize};
|
||
use uniffi_macros::include_scaffolding;
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct Greeting {
|
||
pub message: String,
|
||
}
|
||
|
||
impl Greeting {
|
||
pub fn new(name: String) -> Greeting {
|
||
Greeting {
|
||
message: format!("Hello, {}!", name),
|
||
}
|
||
}
|
||
|
||
pub fn greet(&self) -> String {
|
||
self.message.clone()
|
||
}
|
||
}
|
||
|
||
include_scaffolding!("my_library");
|
||
```
|
||
3. 编写 UDL 文件
|
||
在项目根目录下创建一个新的文件 src/my_library.udl,用于定义接口描述语言 (UDL)。
|
||
```rs
|
||
namespace my_library {
|
||
struct Greeting {
|
||
message: string;
|
||
}
|
||
|
||
Greeting {
|
||
static Greeting new(string name);
|
||
string greet();
|
||
}
|
||
}
|
||
```
|
||
这个 UDL 文件描述了 Greeting 结构体及其方法。
|
||
|
||
#### 4. 生成 Uniffi 绑定
|
||
使用 UniFFI 工具生成 Swift 绑定文件。确保你在项目根目录下,然后运行以下命令:
|
||
```shell
|
||
uniffi-bindgen generate src/my_library.udl --language swift --out-dir gen/
|
||
```
|
||
该命令将生成必要的 Swift 文件,并保存在gen/目录下。
|
||
|
||
#### 5. 构建 Rust 库
|
||
使用以下命令构建 Rust 库:
|
||
```shell
|
||
cargo build --release
|
||
```
|
||
生成的动态库文件将位于 target/release 目录下,文件名为 libmy_rust_library.dylib(在 macOS 上)。
|
||
|
||
通过上述步骤,我们创建了一个简单的 Rust 库,并配置了 Uniffi 以生成 Swift 绑定文件。在下一部分中,我们将把生成的 Swift 文件集成到 Swift 项目中,并编写代码调用 Rust 库。
|
||
|
||
#### 6. 生成 UniFFI 绑定
|
||
在这一部分,我们将使用 UniFFI 工具生成 Swift 绑定代码。这将使得我们可以在 Swift 项目中调用 Rust 库的功能。
|
||
|
||
1. 编写 UDL 文件
|
||
首先,我们需要编写一个 UniFFI 接口描述语言 (UDL) 文件。这个文件描述了我们希望暴露给 Swift 的数据结构和函数接口。
|
||
在项目根目录的 src 文件夹中创建一个名为 my_library.udl 的文件,并添加以下内容:
|
||
```rs
|
||
namespace my_library {
|
||
struct Greeting {
|
||
message: string;
|
||
}
|
||
|
||
Greeting {
|
||
static Greeting new(string name);
|
||
string greet();
|
||
}
|
||
}
|
||
```
|
||
这个 UDL 文件定义了一个名为 Greeting 的结构体及其两个方法:new 和 greet
|
||
|
||
|
||
2. 生成 Swift 绑定
|
||
在终端中导航到项目根目录,并运行以下命令生成 Swift 绑定:
|
||
```shell
|
||
uniffi-bindgen generate src/my_library.udl --language swift --out-dir gen/
|
||
```
|
||
这个命令会根据 my_library.udl 文件生成 Swift 绑定代码,并将其放在 `gen/` 目录下。生成的文件包括:
|
||
- my_library.swift:包含 Swift 代码,用于调用 Rust 库。
|
||
- my_libraryFFI.h:C 头文件,用于描述 Rust 和 Swift 之间的接口。
|
||
- my_libraryFFI.swift:内部使用的 Swift 文件,处理底层的 FFI 调用。
|
||
|
||
下是生成的 my_library.swift 文件的示例内容:
|
||
|
||
```swift
|
||
import Foundation
|
||
|
||
public struct Greeting {
|
||
public let message: String
|
||
|
||
public init(name: String) {
|
||
self = Greeting.new(name: name)
|
||
}
|
||
|
||
public func greet() -> String {
|
||
return greeting_greet(self)
|
||
}
|
||
}
|
||
```
|
||
|
||
my_libraryFFI.h 文件的示例内容:
|
||
```c
|
||
#ifndef MY_LIBRARY_FFI_H
|
||
#define MY_LIBRARY_FFI_H
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
|
||
typedef struct {
|
||
char* message;
|
||
} Greeting;
|
||
|
||
Greeting* greeting_new(const char* name);
|
||
const char* greeting_greet(const Greeting* self);
|
||
void greeting_free(Greeting* self);
|
||
|
||
#endif // MY_LIBRARY_FFI_H
|
||
```
|
||
|
||
3. 构建 Rust 库
|
||
在继续之前,确保 Rust 库可以成功构建。运行以下命令:
|
||
```shell
|
||
cargo build --release
|
||
```
|
||
生成的动态库文件位于 `target/release` 目录下,文件名为 libmy_rust_library.dylib(在 macOS 上)。这个文件将被 Swift 项目使用。
|
||
通过以上步骤,你已经成功生成了用于 Swift 调用的 Rust 绑定文件。在下一部分中,我们将这些文件集成到 Swift 项目中,并编写代码调用 Rust 库。
|
||
|
||
#### 集成到 Swift 项目
|
||
1. 打开 Finder,导航到 Rust 项目中的 `gen/` 目录,选择 my_library.swift、my_libraryFFI.h、my_libraryFFI.swift 文件。
|
||
拖动这些文件到 Xcode 项目导航器中的项目目录下。在弹出的对话框中,确保选中 "Copy items if needed" 选项,然后点击 "Finish"。
|
||
|
||
2. 添加 Rust 动态库
|
||
为了让 Swift 项目能够找到并使用 Rust 动态库,需要将动态库文件添加到 Xcode 项目中:
|
||
- 在 Finder 中,导航到 Rust 项目的target/release目录。
|
||
- 找到生成的动态库文件libmy_rust_library.dylib(在 macOS 上)。
|
||
- 拖动这个文件到 Xcode 项目导航器中的项目目录下。在弹出的对话框中,确保选中 "Copy items if needed" 选项,然后点击 "Finish"。
|
||
|
||
3. 配置 Xcode 项目
|
||
为了让 Xcode 项目能够正确地链接和加载 Rust 动态库,需要进行一些配置:
|
||
- 选择项目文件,在左侧的 "TARGETS" 列表中选择你的应用目标。
|
||
- 选择 "Build Phases" 选项卡。
|
||
- 展开 "Link Binary With Libraries" 部分,点击 "+" 按钮,添加刚才拖动到项目中的 libmy_rust_library.dylib 文件。
|
||
|
||
4. 配置动态库加载路径
|
||
选择项目文件,在左侧的 "TARGETS" 列表中选择你的应用目标。
|
||
- 选择 "Build Settings" 选项卡。
|
||
- 搜索 "Runpath Search Paths"。
|
||
- 添加以下路径到 "Runpath Search Paths" 配置项中:`@executable_path/../Frameworks`
|
||
|
||
5. 编写 Swift 调用代码
|
||
在 ViewController.swift 文件中,编写代码调用 Rust 库:
|
||
```swift
|
||
import UIKit
|
||
|
||
class ViewController: UIViewController {
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
|
||
// 调用 Rust 库
|
||
let greeting = Greeting(name: "World")
|
||
print(greeting.greet())
|
||
}
|
||
}
|
||
```
|
||
|
||
通过这些步骤,已经掌握了如何在 Swift 项目中高效地使用 Rust 库,并了解了相关的高级技术。这种跨语言的集成不仅能利用 Rust 的性能优势,还能享受 Swift 的便捷开发体验。
|