Python 3.11.0
rustc 1.68.0 (2c8cc3432 2023-03-06)
Mac
c++或rust
anoidrd生成so文件, ios生成.a文件
通过ffi间接调用
#include
#include
extern "C" {
__attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t x, int32_t y) {
return x + y;
}
__attribute__((visibility("default"))) __attribute__((used))
int32_t native_add2(int32_t x, int32_t y) {
return x + y;
}
__attribute__((visibility("default"))) __attribute__((used))
char* concat(const char* str1, const char* str2) {
int len1 = strlen(str1);
int len2 = strlen(str2);
char* result = new char[len1 + len2 + 1];
strcpy(result, str1);
strcat(result, str2);
return result;
}
}
extern "C" __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add3(int32_t x, int32_t y) {
return x + y;
}
cmake_minimum_required(VERSION 3.18.1) # for example
add_library(native_lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
../ios/Runner/native_lib.cpp )
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "../CMakeLists.txt"
}
}
ndk.dir=C:\sdk\androidsdk\Android\Sdk\ndk\24.0.8215888
import 'dart:ffi' as ffi;
import 'dart:ffi';
import 'dart:io'; // For Platform.isX
import 'package:ffi/ffi.dart';
final DynamicLibrary nativeAddLib = Platform.isAndroid
? DynamicLibrary.open("libnative_lib.so")
: DynamicLibrary.process();
final int Function(int x, int y) nativeAdd = nativeAddLib
.lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add")
.asFunction();
final int Function(int x, int y) nativeAdd2 = nativeAddLib
.lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add2")
.asFunction();
final int Function(int x, int y) nativeAdd3 = nativeAddLib
.lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add3")
.asFunction();
typedef A2 = Pointer<Utf8> Function(ffi.Pointer<Utf8>, ffi.Pointer<Utf8>);
String concatStr(String str1, String str2) {
final privateKeyPtr = str1.toNativeUtf8();
final hexCidMessagePtr = str2.toNativeUtf8();
final concat =
nativeAddLib.lookup<ffi.NativeFunction<A2>>('concat').asFunction<A2>();
return concat(privateKeyPtr, hexCidMessagePtr).toDartString();
}
bool isExistSymbol(String symbol) {
final isOk = nativeAddLib.providesSymbol(symbol);
return isOk;
}
flutter_rust_bridge: ^1.71.0
ffi: ^2.0.1
ffigen: ^7.2.8
cargo new --lib native
拷贝api.rs,lib.rs
//lib.rs
mod api;
mod bridge_generated;
//api.ts
// This is the entry point of your Rust library.
// When adding new code to your project, note that only items used
// here will be transformed to their Dart equivalents.
// A plain enum without any fields. This is similar to Dart- or C-style enums.
// flutter_rust_bridge is capable of generating code for enums with fields
// (@freezed classes in Dart and tagged unions in C).
pub enum Platform {
Unknown,
Android,
Ios,
Windows,
Unix,
MacIntel,
MacApple,
Wasm,
}
// A function definition in Rust. Similar to Dart, the return type must always be named
// and is never inferred.
pub fn platform() -> Platform {
// This is a macro, a special expression that expands into code. In Rust, all macros
// end with an exclamation mark and can be invoked with all kinds of brackets (parentheses,
// brackets and curly braces). However, certain conventions exist, for example the
// vector macro is almost always invoked as vec![..].
//
// The cfg!() macro returns a boolean value based on the current compiler configuration.
// When attached to expressions (#[cfg(..)] form), they show or hide the expression at compile time.
// Here, however, they evaluate to runtime values, which may or may not be optimized out
// by the compiler. A variety of configurations are demonstrated here which cover most of
// the modern oeprating systems. Try running the Flutter application on different machines
// and see if it matches your expected OS.
//
// Furthermore, in Rust, the last expression in a function is the return value and does
// not have the trailing semicolon. This entire if-else chain forms a single expression.
if cfg!(windows) {
Platform::Windows
} else if cfg!(target_os = "android") {
Platform::Android
} else if cfg!(target_os = "ios") {
Platform::Ios
} else if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
Platform::MacApple
} else if cfg!(target_os = "macos") {
Platform::MacIntel
} else if cfg!(target_family = "wasm") {
Platform::Wasm
} else if cfg!(unix) {
Platform::Unix
} else {
Platform::Unknown
}
}
// The convention for Rust identifiers is the snake_case,
// and they are automatically converted to camelCase on the Dart side.
pub fn rust_release_mode() -> bool {
cfg!(not(debug_assertions))
}
pub fn test() -> String {
String::from("这是一个rust函数")
}
Cargo.toml
[package]
name = "native"
version = "0.1.0"
edition = "2021"
[lib]
name = "native"
crate-type = ["staticlib", "cdylib"]
[build-dependencies]
flutter_rust_bridge_codegen = "=1.71.0"
[dependencies]
flutter_rust_bridge = "=1.71.0"
flutter_rust_bridge_macros = "=1.71.0"
flutter_rust_bridge_codegen \
--rust-input native/src/api.rs \
--dart-output lib/bridge_generated.dart \
--c-output ios/Classes/bridge_generated.h
cargo install flutter_rust_bridge_codegen
android相关
cargo install cargo-ndk
rustup target add aarch64-linux-android
rustup target add armv7-linux-androideabi
rustup target add x86_64-linux-android
rustup target add i686-linux-android
ios相关
64 bit targets (真机 & 模拟器):
rustup target add aarch64-apple-ios x86_64-apple-ios
New simulator target for Xcode 12 and later
ustup target add aarch64-apple-ios-sim
ANDROID_NDK=/Users/yujunlong/Library/Android/sdk/ndk/24.0.8215888
[
Debug: null,
Profile: '--release',
Release: '--release'
].each {
def taskPostfix = it.key
def profileMode = it.value
tasks.whenTaskAdded { task ->
if (task.name == "javaPreCompile$taskPostfix") {
task.dependsOn "cargoBuild$taskPostfix"
}
}
tasks.register("cargoBuild$taskPostfix", Exec) {
workingDir "../../native"
environment ANDROID_NDK_HOME: "$ANDROID_NDK"
commandLine 'cargo', 'ndk',
// the 2 ABIs below are used by real Android devices
'-t', 'armeabi-v7a',
'-t', 'arm64-v8a',
'-t', 'x86',
'-t', 'x86_64',
'-o', '../android/app/src/main/jniLibs', 'build'
if (profileMode != null) {
args profileMode
}
}
}
在native(rust项目下面)下面执行
cargo xcode
在 Xcode 中打开 ios/Runner.xcodeproj
xcode中选中Runner 然后File —> Add Files to “Runner”
native.xcodeproj
点击 Runner 根项目,TARGETS —> Build Phases —> Target Dependencies :请添加 native-staticlib
展开 Link Binary With Libraries:添加 libnative_static.a
#import "GeneratedPluginRegistrant.h"
#import "bridge_generated.h"
print(“dummy_value=(dummy_method_to_enforce_bundling())”);
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
print("dummy_value=\(dummy_method_to_enforce_bundling())");
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Flutter和Rust如何优雅的交互
flutter_rust_bridge
flutter调用cpp