当前位置:   article > 正文

完整流程 Flutter 集成 Rust 多语言跨端开发基础案例_rust 写跨端组件

rust 写跨端组件

使用Rust一处编写,横跨中Android & IOS 多端场景使用,相比较 React Native 方案更加高效。并且Rust是一门系统级编程,Rust编写也可以在其它场景下复用。
本文主要介绍了Flutter 集成Rust,所以并不会在Flutter、Rust等开发环境搭建以及Dart、Rust语言上做介绍。
考虑Android & IOS 同时使用,所以本文使用MacOS系统作为演示,如仅仅需做安卓上测试可跳过相关IOS的配置等操作。

本地环境

Flutter 版本

Flutter版本

Rust 版本

rustc 1.61.0 (fe5b13d68 2022-05-18)
cargo 1.61.0 (a028ae42f 2022-04-29)
  • 1
  • 2

NDK 版本

可通过 Android Studio 安装 NDK 版本 22.1.7171670
测过着23版本之后cargo 构建编译会出问题
  • 1
  • 2

配置 NDK 环境变量

此处使用VSCode编辑器编辑
ANDROID_NDK_HOME 指定 NDK 安装目录

code ~/.zshrc
export ANDROID_NDK_HOME=/Users/username/Library/Android/sdk/ndk/22.1.7171670
source ~/.zshrc
  • 1
  • 2
  • 3

生成交叉编译工具

mkdir ~/.NDK
python3 $ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --api 21 --arch arm64 --install-dir ~/.NDK/arm64
python3 $ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --api 16 --arch arm --install-dir ~/.NDK/arm
python3 $ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --api 16 --arch x86 --install-dir ~/.NDK/x86
  • 1
  • 2
  • 3
  • 4

配置Rust交叉编译工具

code ~/.cargo/config
[target.aarch64-linux-android]
ar = ".NDK/arm64/bin/aarch64-linux-android-ar"
linker = ".NDK/arm64/bin/aarch64-linux-android-clang"

[target.armv7-linux-androideabi]
ar = ".NDK/arm/bin/arm-linux-androideabi-ar"
linker = ".NDK/arm/bin/arm-linux-androideabi-clang"

[target.i686-linux-android]
ar = ".NDK/x86/bin/i686-linux-android-ar"
linker = ".NDK/x86/bin/i686-linux-android-clang"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

下载Rust 交叉编译的依赖

Android

rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android
  • 1

IOS

rustup target add aarch64-apple-ios x86_64-apple-ios
  • 1

安装cargo-lipo以生成iOS通用库

cargo install cargo-lipo
  • 1

Rust 项目相关

创建项目

cargo init my-app-base --lib
  • 1

编写功能

使用任意编辑器打开项目,编辑src中lib.rs文件,添加如下代码,其中定义了一个hello输出world字符以及count_add_self每次调用加2

use std::os::raw::c_char;
use std::ffi::CString;

static mut COUNT: u32 = 0;

#[no_mangle]
pub unsafe extern "C" fn count_add_self() -> u32 {
    COUNT += 2;
    COUNT
}

#[no_mangle]
pub unsafe extern fn hello() -> *const c_char {
    let s = CString::new("world").unwrap();
    s.into_raw()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

修改配置

修改 Cargo.toml 文件增加如下内容

Rust 构建出来的二进制库
在 IOS 中是静态链接进最终的程序之中,需要对构建 staticlib 的支持
在 Android 是通过动态链接在运行时装在进程序运行空间的,需要对构建 cdylib 的支持

[lib]
name = "hello_lib"
crate-type = ["staticlib", "cdylib"]
  • 1
  • 2
  • 3

编译Rust得到静态库

# IOS
cargo lipo --release
# Android
cargo build --target aarch64-linux-android --release     
cargo build --target armv7-linux-androideabi --release     
cargo build --target i686-linux-android --release
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Flutter 项目相关

使用Android Studio、VSCode或者终端创建一个Flutter项目

IOS 引入Rust静态库

  1. 在Flutter项目ios目录下新建Framework文件夹

  2. 将Rust项目中target/universal/release/libhello_lib.a 复制到 Framework 文件夹
    复制静态库

  3. 在 ios 目录上右键使用 xcode 打开项目

  4. 在 Build Phases 中 Link Binary With Libraries 添加 Framework文件夹中 libhello_lib.a 文件
    xcode添加静态库

  5. 在 Build Settings 中 Other Linker Flags 中添加 -all_load 的参数
    xcode配置参数

  6. 在 Build Settings 中 Architectures 中 Excluded Architectures 添加 arm64 的参数,默认应该有一个 i386 因为Rust编译后的是 arm64 架构
    添加arm64架构

Android 引入Rust静态库

在Flutter项目android/app/src/main目录下新建jniLibs目录,并在新建 arm64-v8a 、 armeabi-v7a 、x86 三个文件夹
添加目录
将 Rust 项目编译后 target 项目下对应架构so文件复制到 对应 架构文件夹下
Rust中so静态库目录
Flutter中so静态库目录

添加FFi依赖

在flutter项目pubspec.yaml中添加FFI

ffi: ^2.0.0
  • 1

FFI

测试调用

在 main.dart 中修改后

import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'dart:io';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  String? hello;

  int count = 0;

  void _incrementCounter() {
    setState(() {
      countAdd();
    });
  }

  @override
  void initState() {
    super.initState();
    final dylib = Platform.isAndroid ? DynamicLibrary.open('libhello_lib.so') :DynamicLibrary.process();
    var result = dylib.lookupFunction<Pointer<Utf8> Function(),Pointer<Utf8> Function()>('hello');
    hello = result().toDartString();
  }

  void countAdd() {
    final dylib = Platform.isAndroid ? DynamicLibrary.open('libhello_lib.so') :DynamicLibrary.process();
    var  countAddSelf = dylib.lookupFunction<Pointer<Uint32> Function(),Pointer<Uint32> Function()>('count_add_self');
    count = countAddSelf().address;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '以下内容为Rust侧结果',
            ),
            Text('$hello'),
            Text('$count'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

测试结果图:

测试结果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/121348?site
推荐阅读
相关标签
  

闽ICP备14008679号