IOS上應用還在半路上,遇到了一些內建問題。在了解、學習過程中發現,IOS的Swifit UI動畫真的是比Flutter做的好幾倍,後面有時間可以記錄記錄。本次先記錄Android內建吧,對比性能的話,可以在rust中for循環個10萬次,對比C的時間消耗。
參考資料
Building and Deploying a Rust library on Android
JNI Create
Create JNI
目錄
一、環境準備
rustup配置
這個配置,在裝rust的時候就配置了,可以忽略。如果沒有配置,想了解的可以看二、Rust入門之Hello World
配置NDK
第一步
先确定自己的NDK目錄
預設目錄一般都在 /Users/你的使用者名/Library/Android/sdk/ndk-bundle 這個位置,使用者目錄可以用 ${HOME} 代替。
第二步
建立庫crate
cargo new android_demo --lib
第三步
切換到 android_demo 項目下,建立 NDK 檔案
找到 make_standalone_toolchain.py 檔案,執行以下語句
python D:/Android/SDK/ndk-bundle/build/tools/make_standalone_toolchain.py --api 26 --arch arm64 --install-dir NDK/arm64
python D:/Android/SDK/ndk-bundle/build/tools/make_standalone_toolchain.py --api 26 --arch arm --install-dir NDK/arm
python D:/Android/SDK/ndk-bundle/build/tools/make_standalone_toolchain.py --api 26 --arch x86 --install-dir NDK/x86
對應的NDK目錄如下
第四步
找到 cargo的配置檔案,~/.cargo/config
[target.aarch64-linux-android]
ar = "E:/VSCodeWorkspace/rust/android_demo/NDK/arm64/bin/aarch64-linux-android-ar"
linker = "E:/VSCodeWorkspace/rust/android_demo/NDK/arm64/bin/aarch64-linux-android-clang"
[target.armv7-linux-androideabi]
ar = "E:/VSCodeWorkspace/rust/android_demo/NDK/arm/bin/arm-linux-androideabi-ar"
linker = "E:/VSCodeWorkspace/rust/android_demo/NDK/arm/bin/arm-linux-androideabi-clang"
[target.i686-linux-android]
ar = "E:/VSCodeWorkspace/rust/android_demo/NDK/x86/bin/i686-linux-android-ar"
linker = "E:/VSCodeWorkspace/rust/android_demo/NDK/x86/bin/i686-linux-android-clang"
其中 E:/VSCodeWorkspace/rust/android_demo 是本次項目目錄。
第五步
添加工具鍊
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android
第六步
在目前 android_demo 目錄下,執行以下語句
編譯Rust項目,按需要的架構編譯即可。
cargo build --target aarch64-linux-android --release
cargo build --target armv7-linux-androideabi --release
cargo build --target i686-linux-android --release
- 出現問題note: %1 不是有效的 Win32 應用程式。 (os error 193) ,第三步和第六步編譯不一緻。解決方法:将第四步,換成Android SDK 目錄下的ndk,看下面代碼示例。error: linker cc not found,解決方案也是按照下面,一定要使用 .cmd
解決方案
[target.aarch64-linux-android]
ar = "D:\\Android\\SDK\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android-ar"
linker = "D:\\Android\\SDK\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android26-clang.cmd"
[target.armv7-linux-androideabi]
ar = "D:\\Android\\SDK\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\arm-linux-androideabi-ar"
linker = "D:\\Android\\SDK\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\armv7a-linux-androideabi26-clang++.cmd"
xxx
産物
二、Rust實作
Cargo.toml
[package]
name = "android_demo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
jni-sys = "0.3.0"
[target.'cfg(target_os="android")'.dependencies]
jni = { version = "0.5", default-features = false }
[lib]
crate-type = ["dylib"]
lib.rs
/*
* @Author: axiong
*/
use std::os::raw::{c_char};
use std::ffi::{CString, CStr};
#[no_mangle]
pub extern fn rust_greeting(to: *const c_char) -> *mut c_char {
let c_str = unsafe { CStr::from_ptr(to) };
let recipient = match c_str.to_str() {
Err(_) => "there",
Ok(string) => string,
};
CString::new("Hello ".to_owned() + recipient).unwrap().into_raw()
}
/// Expose the JNI interface for android below
/// 隻有在目标平台是Android的時候才開啟 [cfg(target_os="android")
/// 由于JNI要求駝峰命名,是以要開啟 allow(non_snake_case)
#[cfg(target_os="android")]
#[allow(non_snake_case)]
pub mod android {
extern crate jni;
use super::*;
use self::jni::JNIEnv;
use self::jni::objects::{JClass, JString};
use self::jni::sys::{jstring};
#[no_mangle]
pub unsafe extern fn Java_com_rjx_rustdemo_RustGreeting_greeting(env: JNIEnv, _: JClass, java_pattern: JString) -> jstring {
// Our Java companion code might pass-in "world" as a string, hence the name.
let world = rust_greeting(env.get_string(java_pattern).expect("invalid pattern string").as_ptr());
// Retake pointer so that we can use it below and allow memory to be freed when it goes out of scope.
let world_ptr = CString::from_raw(world);
let output = env.new_string(world_ptr.to_str().unwrap()).expect("Couldn't create java string!");
output.into_inner()
}
}
三、Android內建
SO內建
RustGreeting.java
public class RustGreeting {
static {
System.loadLibrary("android_demo");
}
private static native String greeting(final String pattern);
public static String sayHello(String to) {
return greeting(to);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
//System.loadLibrary("native-lib");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(RustGreeting.sayHello("Rust!!"));
}
}
效果
作者:CodeOver
連結:https://juejin.cn/post/7170696817682694152
來源:稀土掘金