Flutter原生工具链Rust镜像插件native_toolchain_rust_mirror的使用

Flutter原生工具链Rust镜像插件native_toolchain_rust_mirror的使用

库用于与rustupcargo交互,当构建用Rust编写的Dart和Flutter原生资产时。

原生资产目前是一个实验性功能,仅在Flutter主分支上可用,并且需要通过flutter config启用:

flutter config --enable-native-assets

使用方法

要将Rust代码与Flutter或Dart包一起构建,需要执行以下步骤:

  1. native_toolchain_rustnative_assets_cli添加为项目的依赖项:
dart pub add native_toolchain_rust
dart pub add native_assets_cli
  1. 在项目根目录下创建一个构建脚本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(
        // 原生资产ID由包名和crate名组成。
        package: '<你的包名>',
        cratePath: 'rust',
        buildConfig: buildConfig,
      );
      await builder.run(output: output);
    });
  } catch (e) {
    // ignore: avoid_print
    print(e);
    exit(1);
  }
}

此假设您的Rust代码位于包根目录下的rust目录中。该crate必须是cdylib

  1. 在您的包根目录中添加native_manifest.yaml文件。这一步不是严格必需的,但它会让native_doctor知道您的包所需的工具链要求:
version: 0.1.0
requirements:
  ndk:
    version: 25.1.8937393
  rust:
    stable:
      version: 1.77.2

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

@ffi.DefaultAsset('package:<flutter包名>/<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,
);

完整的示例可以在这里查看。

使用包含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原生工具链Rust镜像插件native_toolchain_rust_mirror的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,以下是一个关于如何在Flutter项目中集成和使用native_toolchain_rust_mirror插件的示例代码和步骤。这个插件假设是用于在Flutter应用中集成Rust代码的原生工具链镜像。需要注意的是,具体的插件实现细节可能有所不同,因此以下示例是一个概念性的展示,实际使用时需要参考插件的官方文档。

步骤一:添加依赖

首先,在你的pubspec.yaml文件中添加native_toolchain_rust_mirror依赖:

dependencies:
  flutter:
    sdk: flutter
  native_toolchain_rust_mirror:
    git:
      url: <插件的Git仓库URL>
      ref: <分支或标签>

确保将<插件的Git仓库URL><分支或标签>替换为实际的仓库地址和版本。

步骤二:配置原生代码

由于native_toolchain_rust_mirror插件涉及到原生代码(Rust),你需要在Flutter项目的原生部分(iOS和Android)进行配置。

iOS配置

  1. 打开ios/目录下的Podfile,确保platform设置支持你的Rust代码所需的最低iOS版本。

  2. ios/目录下运行pod install来更新Pod配置。

Android配置

  1. 编辑android/app/build.gradle文件,确保minSdkVersiontargetSdkVersion适合你的Rust代码需求。

  2. android/settings.gradle文件中,确保包含了必要的原生模块配置(如果有的话)。

步骤三:编写Rust代码

创建一个Rust库,并将其编译为动态链接库(例如.so文件用于Android,.dylib文件用于iOS)。这里假设你已经有了一个简单的Rust库。

// libmy_rust_code.rs
#[no_mangle]
pub extern "C" fn hello_from_rust() -> *const u8 {
    b"Hello from Rust!\0" as *const u8
}

编译这个Rust库为动态链接库,具体命令取决于你的操作系统和目标平台。

步骤四:集成Rust库到Flutter

Android

将编译好的.so文件放到android/app/src/main/jniLibs/<abi>/目录下,其中<abi>是目标架构(如armeabi-v7a, arm64-v8a, x86, x86_64)。

在Flutter中,使用MethodChannel来调用Rust函数:

import 'package:flutter/services.dart';

class NativeRustBridge {
  static const MethodChannel _channel = MethodChannel('native_toolchain_rust_mirror');

  static Future<String> getHelloFromRust() async {
    final String result = await _channel.invokeMethod('helloFromRust');
    return result;
  }
}

在原生Android代码中(如MainActivity.ktMainActivity.java),设置MethodChannel并处理来自Dart的调用:

// MainActivity.java
import android.os.Bundle;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "native_toolchain_rust_mirror";

    @Override
    public void configureFlutterEngine(FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(
                        (call, result) -> {
                            if (call.method.equals("helloFromRust")) {
                                // 调用Rust函数并返回结果
                                String hello = callRustFunction();
                                result.success(hello);
                            } else {
                                result.notImplemented();
                            }
                        }
                );
    }

    private native String callRustFunction();

    // 加载Rust库
    static {
        System.loadLibrary("my_rust_code");
    }
}

iOS

将编译好的.dylib文件添加到Xcode项目中,并确保它被正确链接。

在Flutter中,同样使用MethodChannel来调用Rust函数(代码与Android相同)。

在原生iOS代码中(如AppDelegate.swiftAppDelegate.m),设置MethodChannel并处理来自Dart的调用:

// AppDelegate.swift
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(name: "native_toolchain_rust_mirror", binaryMessenger: controller)
        channel.setMethodCallHandler({
            (call: FlutterMethodCall, result: @escaping FlutterResult) in
            if call.method == "helloFromRust" {
                let hello = self.callRustFunction()
                result(hello)
            } else {
                result(FlutterMethodNotImplemented)
            }
        })
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    private func callRustFunction() -> String {
        // 调用Rust函数并返回结果
        // 注意:这里需要实现与Rust库的交互,可能涉及到桥接代码
        return "Hello from Rust!" // 占位符,实际应调用Rust函数
    }
}

注意事项

  • Rust代码与Flutter的交互通常需要通过C接口进行,确保Rust函数使用extern "C"声明,并且避免名称修饰(name mangling)。
  • 编译Rust库时,需要根据目标平台(Android, iOS)设置相应的编译目标。
  • 在实际项目中,可能需要更复杂的桥接代码来处理数据传递和错误处理。

以上是一个概念性的示例,具体实现细节可能因项目需求和插件实现而异。务必参考native_toolchain_rust_mirror插件的官方文档和示例代码。

回到顶部