Files
knowledge-kit/Chapter1 - iOS/1.147.md
2025-12-30 21:07:15 +08:00

13 KiB
Raw Blame History

Rust 在移动端可以做什么

uniffi 的思路,和早期类似营销计算的逻辑用 ts 写好,端上 js 引擎加速Android、iOS 再去使用是一个思路。

一、Uniffi 在移动端能做什么?

1. uniffi 是什么?

uniffi全称 “Uniffi-rs”是 Mozilla 开发的一个跨语言绑定生成工具,核心作用是让 Rust 代码能被其他编程语言(如 Swift、Kotlin、Python、JavaScript 等)无缝调用,通过自动生成类型安全的绑定层,大幅简化跨语言 FFIForeign 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 可以做什么?

移动端开发的核心痛点之一是 “iOSSwift/Objective-C和 AndroidKotlin/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 高效互操作性

UniFFIUniversal Foreign Function Interface是一个工具集旨在帮助开发者轻松生成适用于多个编程语言如 Swift、Kotlin 和 Python的外部函数接口 (FFI) 绑定。它允许你通过定义一个接口描述语言 (UDL) 文件,自动生成跨语言的绑定代码,从而简化 Rust 代码与其他语言之间的交互。

1. 必要工具

开始之前,你需要确保已经安装了以下工具:

  • Rust 和 CargoRust 是一种系统编程语言强调安全性和性能。Cargo 是 Rust 的包管理器和构建系统。 验证安装:运行以下命令确保 Rust 和 Cargo 已正确安装。
rustc --version
cargo --version
  • UniFFI CLI 工具UniFFI 提供了一个命令行工具,用于生成绑定代码。安装 UniFFI你可以通过 Cargo 安装 UniFFI。
cargo install uniffi_bindgen

验证安装:运行以下命令确保 UniFFI 已正确安装。

uniffi-bindgen --version

2. 项目设置

  1. 创建 Rust 项目
  • 打开终端并运行以下命令创建一个新的 Rust 库项目:
cargo new my_rust_library --lib
cd my_rust_library
  • 编辑Cargo.toml文件添加 Uniffi 依赖项
[dependencies]
uniffi = "0.27.0" 
serde = { version = "1.0", features = ["derive"] }
  • 配置Cargo.toml文件中的lib部分设置 crate 类型为 cdylib
[lib]
crate-type = ["cdylib"]
  1. 创建名为 MySwiftApp 的Swift 项目

3. Rust 库的创建

我们将创建一个简单的 Rust 库,并配置它以便与 Swift 互操作。我们将定义一个数据结构和一些基本的功能,使用 UniFFI 来生成绑定。

  1. 设置 Cargo.toml 首先,我们需要在 Cargo.toml 文件中配置项目依赖和库类型:
[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"]
  1. 编写 Rust 代码 在 src/lib.rs 文件中编写 Rust 代码。我们将定义一个简单的结构体 Greeting 和相关的方法。
// 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");
  1. 编写 UDL 文件 在项目根目录下创建一个新的文件 src/my_library.udl用于定义接口描述语言 (UDL)。
namespace my_library {
    struct Greeting {
        message: string;
    }

    Greeting {
        static Greeting new(string name);
        string greet();
    }
}

这个 UDL 文件描述了 Greeting 结构体及其方法。

4. 生成 Uniffi 绑定

使用 UniFFI 工具生成 Swift 绑定文件。确保你在项目根目录下,然后运行以下命令:

uniffi-bindgen generate src/my_library.udl --language swift --out-dir gen/

该命令将生成必要的 Swift 文件并保存在gen/目录下。

5. 构建 Rust 库

使用以下命令构建 Rust 库:

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 的文件,并添加以下内容:
namespace my_library {
    struct Greeting {
        message: string;
    }

    Greeting {
        static Greeting new(string name);
        string greet();
    }
}

这个 UDL 文件定义了一个名为 Greeting 的结构体及其两个方法new 和 greet

  1. 生成 Swift 绑定 在终端中导航到项目根目录,并运行以下命令生成 Swift 绑定:
uniffi-bindgen generate src/my_library.udl --language swift --out-dir gen/

这个命令会根据 my_library.udl 文件生成 Swift 绑定代码,并将其放在 gen/ 目录下。生成的文件包括:

  • my_library.swift包含 Swift 代码,用于调用 Rust 库。
  • my_libraryFFI.hC 头文件,用于描述 Rust 和 Swift 之间的接口。
  • my_libraryFFI.swift内部使用的 Swift 文件,处理底层的 FFI 调用。

下是生成的 my_library.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 文件的示例内容:

#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
  1. 构建 Rust 库 在继续之前,确保 Rust 库可以成功构建。运行以下命令:
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"。
  1. 配置 Xcode 项目 为了让 Xcode 项目能够正确地链接和加载 Rust 动态库,需要进行一些配置:
  • 选择项目文件,在左侧的 "TARGETS" 列表中选择你的应用目标。
  • 选择 "Build Phases" 选项卡。
  • 展开 "Link Binary With Libraries" 部分,点击 "+" 按钮,添加刚才拖动到项目中的 libmy_rust_library.dylib 文件。
  1. 配置动态库加载路径 选择项目文件,在左侧的 "TARGETS" 列表中选择你的应用目标。
  • 选择 "Build Settings" 选项卡。
  • 搜索 "Runpath Search Paths"。
  • 添加以下路径到 "Runpath Search Paths" 配置项中:@executable_path/../Frameworks
  1. 编写 Swift 调用代码 在 ViewController.swift 文件中,编写代码调用 Rust 库:
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // 调用 Rust 库
        let greeting = Greeting(name: "World")
        print(greeting.greet())
    }
}

通过这些步骤,已经掌握了如何在 Swift 项目中高效地使用 Rust 库,并了解了相关的高级技术。这种跨语言的集成不仅能利用 Rust 的性能优势,还能享受 Swift 的便捷开发体验。