本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2021/09/15/flutter-with-rust/
Rust语言本身就是跨平台的,加上很多性能上的优势,很多代码可以在一定程度上复用。
Flutter的FFI支持可以让我们调用本地代码,也就是可以做到Flutter和Rust混合编程。
Rust改造
为了减少改动,我一般会引入一个新的项目,直接在原项目名基础上加上ffi。
这个项目的主要用途在于定义对外暴露的接口,并在构建时输出so等文件。
在Cargo.toml中新增两个依赖
[dependencies]
rust-project = { path = "../rust-project" }
[build-dependencies]
cbindgen = "0.14.3"
dart-bindgen = "0.1.7"
其中cbindgen帮助我们从Rust代码生成C/C++的头文件,dart-bindgen(现在用ffigen了)帮助我们从头文件生成dart绑定。
Flutter插件
有了上一步的so和dart文件后我们就可以调用了,但是出于隔离和复用的考虑,这里不直接在Flutter项目中使用,而是先包装成Plugin。
按照设计,Flutter插件可以用于封装与平台专用代码进行的通信,由于上一步已经生成了绑定,所以这里只做最基础的封装和注册。
import 'ffi.dart' as ffi;
class Plugin {
int functionName(int a, int b) {
return ffi.functionName(a, b);
}
}
在android平台中新增注册
package com.example.adder
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
/** AdderPlugin */
public class AdderPlugin: FlutterPlugin, MethodCallHandler {
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "adder")
channel.setMethodCallHandler(AdderPlugin());
}
// This static function is optional and equivalent to onAttachedToEngine. It supports the old
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
//
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "adder")
channel.setMethodCallHandler(AdderPlugin())
}
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
}
}
Flutter调用
插件的使用和普通的基本一致,只是在依赖中使用路径。
这里注意一点,x86的flutter.so有些版本只有debug版本,release后返回会报错,但是rust生成的so不涉及这个问题,如果有闪退注意看错误日志。
Cargo-make
这里是一个可选项目,由于混合编程设计的构建和依赖比较多,一般都会用脚本或者其他方式管理。如果熟悉Makefile自然可以用,如果不怎么接触的可以考虑下Cargo-make。
可以处理常见的依赖安装、操作系统判断、基础函数、任务依赖等。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2021/09/15/flutter-with-rust/