flutter/dart通过ffi调用rust代码
flutter/dart通过ffi调用rust
·
ffi简介
FFI(Foreign Function Interface)是用来与其它语言交互的接口,在有些语言里面称为语言绑定(language bindings),Java 里面一般称为 JNI(Java Native Interface) 或 JNA(Java Native Access)。由于现实中很多程序是由不同编程语言写的,必然会涉及到跨语言调用,比如 A 语言写的函数如果想在 B 语言里面调用,这时一般有两种解决方案:一种是将函数做成一个服务,通过进程间通信(IPC)或网络协议通信(RPC, RESTFul等);另一种就是直接通过 FFI 调用。前者需要至少两个独立的进程才能实现,而后者直接将其它语言的接口内嵌到本语言中,所以调用效率比前者高。
rust代码
- 创建一个文件夹,如flutter-ffi-rust,然后进入flutter-ffi-rust文件夹执行:cargo new rust_ffi
- 进入rust_ffi执行:cargo run,确保创建的rust项目可以执行
- 在Cargo.toml文件中添加代码如下:
[lib]
name = "casher"
crate-type = ["cdylib"]
- 将mian.rs改为lib.rs,将如下代码粘贴进去:
use std::io::Write;
use std::ffi::CStr;
use std::os::raw::c_char;
#[no_mangle]
pub extern "C" fn play_once(ptr: *const c_char) -> u32 {
let cstr = unsafe { CStr::from_ptr(ptr)};
let a = cstr.to_str().unwrap();
let mut file = std::fs::File::create("data.txt").expect("create failed");
file.write_all("简单测试121212".as_bytes()).expect("write failed");
file.write_all("\n简单编程".as_bytes()).expect("write failed");
println!("data written to file" );
println!("data written to file----{}",a);
let return_num = 10;
return_num
}
#[no_mangle]
pub extern "C" fn play_once_test(ptr: *const c_char) -> u32 {
let cstr = unsafe { CStr::from_ptr(ptr)};
let a = cstr.to_str().unwrap();
println!("data written to file-----------{}",a);
let mut file = std::fs::File::create("datatest.txt").expect("create failed");
file.write_all("简单教程测试".as_bytes()).expect("write failed");
file.write_all("\n简单编程测试".as_bytes()).expect("write failed");
println!("data written to file" );
let s = 11;
s
}
- 执行cargo build,然后target/debug下面会出现一个ibcasher.dylib文件,注意:在Linux上会创建*.so文件,在MacOSX上会创建*.dylib文件,在Windows上会创建*.dll文件,我是macos,所以会生成dylib文件
dart代码
- 在flutter-ffi-rust文件夹下创建flutter项目,执行dart create flutter_ffi
- 进入flutter_ffi里面执行dart run,确保创建的flutter项目正确,然后执行 dart pub add ffi 或者在pubspec.yaml 安装 ffi: ^1.2.1
- 将如下代码粘入bin/flutter_ffi.dart里面:
import 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart';
typedef playOnceFunc = ffi.Void Function(ffi.Pointer<Utf8>);
typedef PlayOnce = void Function(ffi.Pointer<Utf8>);
void main() {
final ffi.DynamicLibrary dylib = ffi.DynamicLibrary.open('libcasher.dylib');
// final PlayOnce play_once = dylib
// .lookup<ffi.NativeFunction<playOnceFunc>>('play_once')
// .asFunction();
// final PlayOnce play_once_test = dylib
// .lookup<ffi.NativeFunction<playOnceFunc>>('play_once_test')
// .asFunction();
const String file_name = '用来测试传递参数';
// Convert a Dart [String] to a Utf8-encoded null-terminated C string.
final ffi.Pointer<Utf8> charPointer = file_name.toNativeUtf8();
var result = dylib.lookupFunction<ffi.Pointer<Utf8> Function(ffi.Pointer<Utf8>),ffi.Pointer<Utf8> Function(ffi.Pointer<Utf8>)>('play_once_test',isLeaf:true);
// play_once(charPointer);
var s = result(charPointer).address;
print("==============");
print(s);
// play_once_test();
}
- 将生成的*.dylib文件放入flutter_ffi文件夹下
- 执行dart run,看调用rust的结果,会生成data.txt文件并写入数据
更多推荐
已为社区贡献4条内容
所有评论(0)