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第三步<br>切換到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/arm64python D:/Android/SDK/ndk-bundle/build/tools/make_standalone_toolchain.py --api 26 --arch arm --install-dir NDK/armpython D:/Android/SDK/ndk-bundle/build/tools/make_standalone_toolchain.py --api 26 --arch x86 --install-dir NDK/x86對應的NDK目錄如下
第四步<br>找到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是本次專案目錄。
第五步<br>新增工具鏈
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android第六步<br>在目前android_demo目錄下,執行以下語句編譯Rust項目,依所需的架構編譯即可。
cargo build --target aarch64-linux-android --releasecargo build --target armv7-linux-androideabi --releasecargo 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
來源:稀土掘金
Comments
Post a Comment