Flutter原生工具链集成插件native_toolchain_rust的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter原生工具链集成插件 native_toolchain_rust 的使用

native_toolchain_rust 是一个用于在构建 Dart 和 Flutter 原生资产时与 rustupcargo 交互的库。该功能目前是实验性的,仅在 Flutter 主分支中可用,并且需要通过 flutter config 启用。

使用步骤

1. 启用 Native Assets

首先,你需要启用 Flutter 的 Native Assets 功能:

flutter config --enable-native-assets

2. 添加依赖

接下来,在你的项目中添加 native_toolchain_rustnative_assets_cli 作为依赖项:

dart pub add native_toolchain_rust
dart pub add native_assets_cli

3. 创建构建脚本

创建一个位于 hook/build.dart 的构建脚本:

import 'dart:io';

import 'package:native_toolchain_rust/native_toolchain_rust.dart';
import 'package:native_assets_cli/native_assets_cli.dart';

void main(List<String> args) async {
  try {
    await build(args, (BuildConfig buildConfig, BuildOutput output) async {
      final builder = RustBuilder(
        // The ID of native assets consists of package name and crate name.
        package: '<your package name>',
        cratePath: 'rust',
        buildConfig: buildConfig,
      );
      await builder.run(output: output);
    });
  } catch (e) {
    // ignore: avoid_print
    print(e);
    exit(1);
  }
}

假设你的 Rust 代码位于包根目录下的 rust 目录中,Crate 必须是一个 cdylib

4. 添加 native_manifest.yaml

为了让你的工具链需求被 native_doctor 工具识别,你可以添加一个 native_manifest.yaml 文件到你的包根目录:

version: 0.1.0
requirements:
  ndk:
    version: 25.1.8937393
  rust:
    stable:
      version: 1.77.2

5. 引用原生资产库

在你的代码中引用原生资产库时,可以使用 @ffi.DefaultAsset 注解:

@ffi.DefaultAsset('package:<flutter_package_name>/<rust_crate_name>')
library rust;

import 'dart:ffi' as ffi;

@ffi.Native<ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr)>()
external int sum(
  int a,
  int b,
);

完整的示例可以参考 GitHub 示例

使用包含 Rust 原生资产的包

如果你的包中包含 Rust 代码,则需要在开发者的机器上安装 Rust 工具链。为了简化这一过程,native_toolchain_rust 会检测 Rust 工具链是否已安装并保持最新版本,如果未安装或版本过旧,它会建议运行 native_doctor 工具来自动安装和配置必要的工具链。

例如,当用户尝试构建你的包而没有安装 Rust 时,他们会收到以下错误消息:

Rustup not found.
Please run native_doctor in your project to fix the issue:

dart pub global activate native_doctor
dart pub global run native_doctor

以下是 native_doctor 在没有 Rust 安装且 NDK 版本过旧的计算机上的输出示例:

Project: example (Flutter)
Buildable platforms: macos, ios, android

Native toolchain: NDK

  [✗] NDK installed, but too old
       ! Installed versions: 23.1.7779620
       ! Required minimum version: 25.1.8937393

Native toolchain: Rust

  [✗] Rustup not found
  [✗] Toolchain stable not installed
       ! Required minimum version: 1.77.2
       ! Missing targets: arm-linux-androideabi, aarch64-linux-android, i686-linux-android,
         x86_64-linux-android, aarch64-apple-ios, x86_64-apple-ios, aarch64-apple-ios-sim, aarch64-apple-darwin,
         x86_64-apple-darwin

Proposed actions:

  • (NDK)  Install NDK 25.1.8937393 or newer
  • (Rust) Install rustup
  • (Rust) Install toolchain stable
  • (Rust) Install targets arm-linux-androideabi, aarch64-linux-android, i686-linux-android,
           x86_64-linux-android, aarch64-apple-ios, x86_64-apple-ios, aarch64-apple-ios-sim, aarch64-apple-darwin,
           x86_64-apple-darwin for toolchain stable

Do you want native doctor to perform proposed actions? (y/N)

确认后,native_doctor 将自动安装正确的 NDK 版本、所需的 Rust 工具链和目标:

 • Fetching NDK list... [done]
 • Installing NDK 26.3.11579264 [done]
 • Installing rustup [done]
 • Installing Rust toolchain stable [done]
 • Installing target arm-linux-androideabi for toolchain stable [done]
 • Installing target aarch64-linux-android for toolchain stable [done]
 • Installing target i686-linux-android for toolchain stable [done]
 • Installing target x86_64-linux-android for toolchain stable [done]
 • Installing target aarch64-apple-ios for toolchain stable [done]
 • Installing target x86_64-apple-ios for toolchain stable [done]
 • Installing target aarch64-apple-ios-sim for toolchain stable [done]
 • Installing target aarch64-apple-darwin for toolchain stable [done]
 • Installing target x86_64-apple-darwin for toolchain stable [done]

更多关于Flutter原生工具链集成插件native_toolchain_rust的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter原生工具链集成插件native_toolchain_rust的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中集成并使用native_toolchain_rust插件的示例代码案例。这个插件允许你在Flutter中使用Rust编写原生代码,并通过FFI(外部函数接口)与Dart代码进行交互。

1. 设置Flutter项目

首先,确保你已经安装了Flutter和Dart SDK,并且已经创建了一个Flutter项目。如果还没有,可以使用以下命令创建一个新的Flutter项目:

flutter create my_flutter_rust_app
cd my_flutter_rust_app

2. 添加native_toolchain_rust依赖

pubspec.yaml文件中,添加native_toolchain_rust作为依赖:

dependencies:
  flutter:
    sdk: flutter
  native_toolchain_rust:
    git:
      url: https://github.com/example/native_toolchain_rust.git  # 假设插件在GitHub上
      ref: main  # 或者其他具体的分支或标签

注意:这里使用了Git URL作为示例,实际使用时请替换为真实的插件仓库地址。

3. 配置CMakeLists.txtbuild.gradle

为了编译Rust代码,需要配置CMake和Gradle。在android/app/CMakeLists.txt中,添加以下内容:

cmake_minimum_required(VERSION 3.10.2)

# 设置Rust目标架构
set(RUST_TARGET_ARCH "x86_64")  # 根据你的目标架构调整
set(RUST_TARGET_OS "android")

# Rust编译命令
add_custom_command(
    OUTPUT ${CMAKE_SOURCE_DIR}/../rust_library/target/${RUST_TARGET_ARCH}-unknown-linux-android/release/libmy_rust_lib.so
    COMMAND cargo
    ARGS build --release --target ${RUST_TARGET_ARCH}-unknown-linux-android
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/../rust_library
    DEPENDS ${CMAKE_SOURCE_DIR}/../rust_library/Cargo.toml
)

# 添加生成的库文件到项目中
add_library(my_rust_lib SHARED IMPORTED)
set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../rust_library/target/${RUST_TARGET_ARCH}-unknown-linux-android/release/libmy_rust_lib.so)

android/app/build.gradle中,确保添加了CMake支持:

android {
    ...
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

4. 编写Rust代码

在项目的根目录下创建一个rust_library文件夹,并在其中创建必要的Rust项目文件,如Cargo.tomlsrc/lib.rs

Cargo.toml

[package]
name = "my_rust_lib"
version = "0.1.0"
edition = "2018"

[lib]
crate-type = ["cdylib"]  # 编译为动态库

[dependencies]

src/lib.rs

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

5. 编写Dart代码调用Rust函数

在Flutter的Dart代码中,使用DynamicLibrary加载并调用Rust函数。例如,在lib/main.dart中:

import 'dart:ffi';
import 'dart:typed_data';

typedef NativeAddFunc = Int32 Function(Int32 a, Int32 b);
typedef AddFunc = int Function(int a, int b);

void main() {
  // 加载Rust动态库
  final DynamicLibrary library = DynamicLibrary.open("libmy_rust_lib.so");

  // 获取Rust函数指针
  final NativeAddFunc nativeAddFunc = library
      .lookup<NativeFunction<NativeAddFunc>>('add')
      .asFunction<NativeAddFunc>();

  // 将Rust函数指针转换为Dart函数
  final AddFunc add = nativeAddFunc as AddFunc;

  // 调用Rust函数
  final int result = add(3, 4);
  print("Result from Rust: $result");
}

6. 运行项目

确保所有配置正确后,使用以下命令运行Flutter项目:

flutter run

如果一切配置正确,你应该能够在控制台中看到Rust函数返回的结果。

这个示例展示了如何在Flutter项目中集成Rust代码,并通过FFI进行调用。根据你的实际需求,你可能需要调整路径、库名、函数名等配置。

回到顶部