Rust语言

关注公众号 jb51net

关闭
首页 > 软件编程 > Rust语言 > Rust Android集成使用

Rust在Android端集成使用详解

作者:良技漫谈

本文介绍了如何在Android平台上调用Rust编写的组件,详细说明了开发环境的搭建、Rust库的创建、配置和编译过程,以及如何在Android应用中使用Rust编写的代码,文中提到飞书底层使用Rust编写通用组件,展示了Rust在移动端开发中的应用价值

Andorid调用Rust

一.开发环境:

开发工具:

1. 如果对android studio比较熟悉,可安装rust插件 

安装完毕,对Rust Toolchain 位置进行配置确认,否则可能对rs文件无法识别,就无法愉快使用studio编写rust

2. 推荐使用VSCode编写rust代码,可以去下载 Visual Studio Code,然后安装rust相关插件即可。

二.创建Android工程:

• 如果对Android比较熟悉,使用studio来创建工程,和其他Android工程创建一样,创建Empty Activity,工程名 AndroidIntegratingRust

先编译通过该空工程,确保依赖资源下载完整。

三,添加rust lib库:

进入到刚创建的AndroidIntegratingRust工程下

1.使用rust Cargo创建 lib库:

Cargo new rust_lib --lib

• 创建成功后会有rust_lib库,结构如下:

├── app
│   ├── build
│   ├── build.gradle
│   ├── libs
│   ├── proguard-rules.pro
│   └── src
├── build
│   └── kotlin
├── build.gradle
├── gradle
│   └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
├── rust_lib //位置在这
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── src
│   └── target
└── settings.gradle

2.编辑Cargo.toml

输入目前需要的jni库依赖, https://crates.io/地址下确认版本, create-type 填写cdylib 动态链接库

[lib]
name = "rust_lib"
crate-type = ["cdylib"]
[dependencies]
jni = "0.20.0"  

3.配置要编译so的linker及target

[target.aarch64-linux-android]
linker = "/Users/android-sdk-macosx/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang++"
[target.armv7-linux-androideabi]
linker = "/Users/android-sdk-macosx/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi21-clang++"

ps: 这是我的mac上ndk所在位置,参考Android官方ndk文档。

 准备编译rust代码为so的环境已经准备完

四,编写Android和Rust代码:

创建Android代码, RustGreetings类, 使用kotlin所以用external声明JNI函数

class RustGreetings {
    fun sayHello(to: String): String {
        return greeting(to)
    }
    companion object {
        @JvmStatic external fun greeting(pattern: String): String
    }
}

在Rust lib库下,编写对应的JNI函数映射,从create.io下可以看到有关JNI的使用,代码如下

use jni::JNIEnv;
// These objects are what you should use as arguments to your native
// function. They carry extra lifetime information to prevent them escaping
// this context and getting used after being GC'd.
use jni::objects::{JClass, JString};
// This is just a pointer. We'll be returning it from our function. We
// can't return one of the objects with lifetime information because the
// lifetime checker won't let us.
use jni::sys::jstring;
// This keeps Rust from "mangling" the name and making it unique for this
// crate.
#[no_mangle]
pub extern "system" fn Java_com_android_integratingrust_RustGreetings_greeting(
    env: JNIEnv,
    // This is the class that owns our static method. It's not going to be used,
    // but still must be present to match the expected signature of a static
    // native method.
    class: JClass,
    input: JString,
) -> jstring {
    // First, we have to get the string out of Java. Check out the `strings`
    // module for more info on how this works.
    let mut input: String = env
        .get_string(input)
        .expect("Couldn't get java string!")
        .into();
    input = append_string(&input);
    // Then we have to create a new Java string to return. Again, more info
    // in the `strings` module.
    let output = env
        .new_string(format!("Hello, {}!", input))
        .expect("Couldn't create java string!");
    // Finally, extract the raw pointer to return.
    output.into_raw()
}
//============== rust code ===============
fn append_string(value: &str) -> String {
    let mut origin = String::from(value);
    origin.push_str("this is Rust");
    return origin;
}
 

五,编译Rust代码为so

aarch64-linux-android
arm-linux-androideabi
armv7-linux-androideabi
i686-linux-android
thumbv7neon-linux-androideabi
x86_64-linux-android

 如果没有安装,需要安装下对应的

rustup target add aarch64-linux-android armv7-linux-androideabi

执行编译

到rust_lib目录下执行编译

cargo build --target aarch64-linux-android --release

 编译成功到target目录下release下去查看对应的so文件

.
├── CACHEDIR.TAG
├── aarch64-linux-android
│   ├── CACHEDIR.TAG
│   └── release
├── armv7-linux-androideabi
│   ├── CACHEDIR.TAG
│   └── release
├── debug
│   ├── build
│   ├── deps
│   ├── examples
│   └── incremental
└── release
    ├── build
    ├── deps
    ├── examples
    └── incremental

六,使用rust代码运行工程

    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/libs']
        }
    }

到此这篇关于Rust在Android端集成使用介绍的文章就介绍到这了,更多相关Rust Android集成使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

阅读全文