【教程】Flutter与Rust完美交互,无需手写FFI代码

这篇具有很好参考价值的文章主要介绍了【教程】Flutter与Rust完美交互,无需手写FFI代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实践环境:Windows11

flutter_rust_bridge官方文档

Flutter环境配置教程 | Rust环境配置教程

新建一个全新的Flutter项目并运行:

flutter create example && cd example && flutter run

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

在Flutter项目根目录新建一个Rust项目:
cargo new native --lib
目录结构大概是这样的:

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

接下来,将这两行添加到 Cargo.toml

[lib]
crate-type = ["staticlib", "cdylib"]


[dependencies]
flutter_rust_bridge = "1.78.0"

[build-dependencies]
flutter_rust_bridge_codegen = "1.78.0"

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 在native/src目录新建一个api.rs

添加以下示例代码:

//api.rs
pub fn hello() -> String {
    format!("{}", "你好,Rust!")
}

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

   lib.rs

//lib.rs
mod api;

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

安装flutter_rust_bridge_codegen

cargo install flutter_rust_bridge_codegen

修改Flutter项目的pubspec.yaml配置文件

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 pubspec.yaml 配置文件完整代码:
name: mobile
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1

environment:
  sdk: ">=3.0.5 <4.0.0"

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  flutter_rust_bridge: 1.77.1
  ffi: ^2.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter

  # The "flutter_lints" package below contains a set of recommended lints to
  # encourage good coding practices. The lint set provided by the package is
  # activated in the `analysis_options.yaml` file located at the root of your
  # package. See that file for information about deactivating specific lint
  # rules and activating additional ones.
  flutter_lints: ^2.0.0
  ffigen: ^8.0.2
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter packages.
flutter:
  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages
运行:
 flutter pub get

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

安装 LLVM (不安装使用生成器的时候会报错):

ubuntu/linux:
sudo apt-get install libclang-dev
Windows:
  1. 安装具有 C++ 开发支持的 Visual Studio。
  2. 安装 LLVM 或使用命令:winget install -e --id LLVM.LLVM
MacOS:
  1. Install Xcode.
  2. Install LLVM - brew install llvm.

切换到flutter项目根目录,运行以下命令,使用flutter_rust_bridge生成器生成代码:

flutter_rust_bridge_codegen -r native/src/api.rs -d lib/ffi/rust_ffi.dart -c ios/Runner/bridge_generated.h

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 现在我们可以看到多了这些文件:

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

接下来在 android/app/build.gradle 最底部插入以下代码:

[
    new Tuple2('Debug', ''),
    new Tuple2('Profile', '--release'),
    new Tuple2('Release', '--release')
].each {
    def taskPostfix = it.first
    def profileMode = it.second
    tasks.whenTaskAdded { task ->
        if (task.name == "javaPreCompile$taskPostfix") {
            task.dependsOn "cargoBuild$taskPostfix"
        }
    }
    tasks.register("cargoBuild$taskPostfix", Exec) {
        // Until https://github.com/bbqsrc/cargo-ndk/pull/13 is merged,
        // this workaround is necessary.

        def ndk_command = """cargo ndk \
            -t armeabi-v7a -t arm64-v8a -t x86_64 -t x86 \
            -o ../android/app/src/main/jniLibs build $profileMode"""

        workingDir "../../native" //native是rust项目目录名称
        environment "ANDROID_NDK_HOME", "D:\\SDK\\Android\\Sdk\\ndk\\25.2.9519653" //这里填写ndk安装路径
        if (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem.isWindows()) {
            commandLine 'cmd', '/C', ndk_command
        } else {
            commandLine 'sh', '-c', ndk_command
        }
    }
}

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 Android设置:

运行以下代码安装cargo-ndk

cargo install cargo-ndk

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 添加工具链:

rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android

我这里已经添加过了

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

进入Rust项目的根目录:

cd native

运行以下命令进行交叉编译:

cargo ndk -t  armeabi-v7a  -o ./jniLibs build --release
cargo ndk -t  arm64-v8a  -o ./jniLibs build --release
cargo ndk -t  x86_64  -o ./jniLibs build --release
cargo ndk -t  x86  -o ./jniLibs build --release

复制Rust项目里的jniLibs目录

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 粘贴到flutter 项目 android/app/main目录

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 编辑flutter项目lib/main.dart文件

import 'dart:ffi';
import 'ffi/rust_ffi.dart';

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 找到_MyHomePageState,加入以下代码

 late Future<String> hello;

  @override
  void initState() {
    super.initState();
    hello = NativeImpl(DynamicLibrary.open('libnative.so')).hello();
  }

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 文章来源地址https://www.toymoban.com/news/detail-655144.html

 调用:

            FutureBuilder<List<dynamic>>(
              future: Future.wait([hello]),
              builder: (context, snap) {
                final data = snap.data;

                if (data == null) return const CircularProgressIndicator();

                // ignore: non_constant_identifier_names
                final Platform = data[0];

                return Text('$Platform');
              },
            )

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 

 main.dart 完整代码:

import 'package:flutter/material.dart';
import 'dart:ffi';
import 'ffi/rust_ffi.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // TRY THIS: Try running your application with "flutter run". You'll see
        // the application has a blue toolbar. Then, without quitting the app,
        // try changing the seedColor in the colorScheme below to Colors.green
        // and then invoke "hot reload" (save your changes or press the "hot
        // reload" button in a Flutter-supported IDE, or press "r" if you used
        // the command line to start the app).
        //
        // Notice that the counter didn't reset back to zero; the application
        // state is not lost during the reload. To reset the state, use hot
        // restart instead.
        //
        // This works for code too, not just values: Most code changes can be
        // tested with just a hot reload.
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  late Future<String> hello;

  @override
  void initState() {
    super.initState();
    hello = NativeImpl(DynamicLibrary.open('libnative.so')).hello();
  }

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // TRY THIS: Try changing the color here to a specific color (to
        // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        // change color while the other colors stay the same.
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          //
          // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
          // action in the IDE, or press "p" in the console), to see the
          // wireframe for each widget.
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            FutureBuilder<List<dynamic>>(
              future: Future.wait([hello]),
              builder: (context, snap) {
                final data = snap.data;

                if (data == null) return const CircularProgressIndicator();

                // ignore: non_constant_identifier_names
                final Platform = data[0];

                return Text('$Platform');
              },
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

  大功告成,现在重新运行项目:

flutter run

【教程】Flutter与Rust完美交互,无需手写FFI代码,rust,flutter,开发语言

 

到了这里,关于【教程】Flutter与Rust完美交互,无需手写FFI代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter Dart FFI Pointer<Uint8>类型如何转成数组或String

    继上一次发布的 Flutter 直接调用so动态库,或调用C/C++源文件内函数 内容,最终我选择了第二种方式, 直接把整个 Native C++ 的项目源代码放进了 Flutter 工程里编译 (放在iOS的目录是因为它不支持自定义源码路径,Android是可以的)。这样的好处是 Android 和 iOS 两个平台都不需要

    2024年02月04日
    浏览(47)
  • Flutter第7天--字体图标+综合小案例+Android代码交互,app架构图

    ); //中间的信息 var center4 = Row( children: [ Expanded(child: pda(center_right, 5)), Image.network( note.imgUrl, width: 80, height: 80, fit: BoxFit.fitHeight ) ], ); var end4 = Row( children: [ Icon( Icons.grade, color: Colors.green, size: 20, ), Text( “1000W”, style: infoStyle,), pd(Icon(Icons.tag_faces, color: Colors.lightBlueAccent, size: 20), l

    2024年04月22日
    浏览(32)
  • 【模型+代码/保姆级教程】使用Pytorch实现手写汉字识别

    参考文章: 最初参考的两篇: 【Pytorch】基于CNN手写汉字的识别 「Pytorch」CNN实现手写汉字识别(数据集制作,网络搭建,训练验证测试全部代码) 模型: EfficientNetV2网络详解 数据集(不必从这里下载,可以看一下它的介绍): CASIA Online and Offline Chinese Handwriting Databases 鉴于

    2024年02月07日
    浏览(41)
  • flutter 手写日历组件

    先看效果  直接上代码 calendar_popup_view.dart custom_calendar.dart hotel_app_theme.dart RangePicker.dart  这个文件是使用的地方 这里还使用到了  getx 的组件 从底部弹出

    2024年02月13日
    浏览(35)
  • flutter手写一个底部导航栏

    使用了一下flutter提供的导航栏,NavigationBar,不过感觉使用起来不是很方便。 譬如说: 不能直接使用图片资源,需要中间加几层转换把图片转化成icon 文本大小及颜色不太好控制 状态栏的上边来一个横线也没有相应的样式,等等。 因此想来想去还是自己写一个吧。 效果如下

    2024年02月12日
    浏览(38)
  • AI国漫女神这样画!傻瓜式的云端SD(stable diffusion)部署教程 - 白嫖4090、无需代码、一键启动

    前段时间一直在用midjourney进行Ai绘画,但是发现Midjourney绘画的限制有点多很死板,很多图都不能画,懂得都懂。想使用Midjourney可以看这个:( 【推荐】Midjourney订阅教程 ) 然后就转到心仪已久的SD(stable diffsion),它的优点很明显 目前源代码在github开源,简称免费; 自定义

    2024年03月15日
    浏览(54)
  • Flutter笔记:手写一个简单的画板工具

    Flutter笔记 手写一个简单的画板工具 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/133418742 在本文中,我们将一起开发一个基本的Flutter画板应用,用户可以在画板上自由绘制,选择不同的颜色来绘

    2024年02月07日
    浏览(35)
  • Flutter 状态栏完美攻略

    Brightness.light 文字黑色 Brightness.dark 文字白色 默认是带个遮罩的,完全去除:

    2024年02月14日
    浏览(31)
  • Flutter笔记:手写并发布一个人机滑动验证码插件

    Flutter笔记 手写一个人机滑块验证码 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/133529459 写 Flutter 项目时,遇到需要滑块验证码功能。滑块验证码属于人机验证码的一种,看起来像是在一个图片

    2024年02月07日
    浏览(35)
  • Flutter 完美的验证码输入框 转载

    刚开始看到这个功能的时候一定觉得so easy,开始的时候我也是这么觉得的,这还不简单,然而真正写的时候才发现并没有想象的那么简单。 先上图,不上图你们都不想看,我难啊,到Github: https://github.com/781238222/flutter-do 上给个小星星可还行,如果能fork一下,那更是感激不

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包