安卓使用rust构建so

尽意
2025-03-20 / 0 评论 / 24 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2025年03月20日,已超过36天没有更新,若内容或图片失效,请留言反馈。

1. 下载和配置 NDK

首先,从 Android NDK 下载页面 下载并安装最新版本的 Android NDK。

在安装完成后,确保能够找到 NDK 的安装路径并配置工具链。您将使用这个工具链来交叉编译 Rust 代码为 Android 的本地库。

2. 创建 Rust 库项目

使用以下命令在命令行中创建一个新的 Rust 库项目:

cargo new android_test_lib --lib

此命令会生成一个新的 Rust 项目目录 android_test_lib,并包含一个简单的库文件结构。

3. 配置 Cargo.toml

编辑项目中的 Cargo.toml 文件,指定该库的构建类型,并添加依赖项:

[package]
name = "android_lib_test"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
jni = "0.21.1"

解释:

  • [lib] 中的 crate-type = ["cdylib"] 指定 Rust 将构建一个 C 兼容的动态库,以便 Android 使用。
  • jni = "0.21.1" 是用于与 Java 进行交互的 JNI 库,允许我们在 Rust 中调用 JNI 方法。

4. 配置 .cargo/config.toml

在项目根目录下创建 .cargo 文件夹,并在其中添加 config.toml 文件,配置 Android 的交叉编译工具链:

mkdir .cargo
touch .cargo/config.toml

目录结构
m8h4l9z0.png

编辑 config.toml 文件,指定交叉编译时使用的工具链路径:

[target.aarch64-linux-android]
linker = "D:/android-ndk-r27c/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang.cmd"
# 注意文件路径

解释:

  • 这里的 linker 配置项指定了 Android NDK 中 clang 编译器的位置,您需要根据自己的实际路径进行修改。

5. 添加目标平台支持

在命令行中运行以下命令,确保您的 Rust 环境支持目标架构:

rustup target list

如果 aarch64-linux-android 目标没有显示为已安装,使用以下命令安装:

rustup target add aarch64-linux-android

6. 编写 Rust 代码

编辑 src/lib.rs 文件,编写您的 Rust 代码并实现 JNI 接口:

use jni::JNIEnv;
use jni::objects::{JClass, JString};
use jni::sys::jstring;

#[no_mangle]
pub extern "system" fn Java_com_suxii_myapplicationrust_Hello_say(
    mut env: JNIEnv,
    class: JClass,
    input: JString,
) -> jstring {
    let world: String = env.get_string(&input).expect("invalid pattern string").into();
    let output = env.new_string(format!("Hello, {}! this is rust", world)).expect("Couldn't create java string!");
    output.into_raw()
}

解释:

  • #[no_mangle]:防止 Rust 编译器对函数名进行修改,以保证 JNI 函数名称与 Java 端的声明一致。
  • extern "system" fn Java_com_suxii_myapplicationrust_Hello_say:JNI 函数,名称必须符合 Java_包名_类名_方法名 的格式。
  • env.get_string(&input).expect("invalid pattern string").into();:将 Java 字符串转换为 Rust 字符串。
  • env.new_string(format!("Hello, {}! this is rust", world)):创建一个新的 Java 字符串并返回给 Java。

7. 编译 Rust 库

使用以下命令为 Android 构建 release 版本的动态库:

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

编译完成后,生成的 libandroid_lib_test.so 文件位于 target/aarch64-linux-android/release/ 目录下。

8. 配置 Android 项目

打开 Android 项目的 app/build.gradle 文件,在 android 块下添加对本地库的支持:

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

    packagingOptions {
        jniLibs {
            useLegacyPackaging = true
        }
    }

    splits {
        abi {
            enable true
            reset()
            include 'arm64-v8a'
            universalApk true
        }
    }
}

解释:

  • jniLibs.srcDirs = ['src/main/jniLibs']:指定 Android 项目中用于存放本地库 .so 文件的目录。
  • useLegacyPackaging = true:使用传统的 JNI 库打包方式。
  • splits.abi { enable true; include 'arm64-v8a'; }:为 arm64-v8a 架构构建 APK。

接下来,在 src/main/ 目录下创建 jniLibs/arm64-v8a/ 目录,并将生成的 libandroid_lib_test.so 文件放入其中。

目录结构为:
m8h4go06.png

9. 创建 Java 接口

在 Android 项目中创建一个新的 Hello 类来调用 Rust 编写的本地方法:

public class Hello {
    static {
        System.loadLibrary("android_lib_test");
    }

    public native String say(String str);
}

解释:

  • System.loadLibrary("android_lib_test");:加载 Rust 编写的本地库。
  • public native String say(String str);:声明本地方法 say,该方法接收一个字符串参数并返回一个字符串。

10. 调用 Rust 函数

在 Java 中,创建 Hello 类的实例并调用 say 方法:

Hello hello = new Hello();
String message = hello.say("World");
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();

解释:

  • Hello hello = new Hello();:创建 Hello 类的实例。
  • String message = hello.say("World");:调用本地方法 say,并传入字符串 "World",获取返回的字符串。
  • Toast.makeText(context, message, Toast.LENGTH_SHORT).show();:将返回的消息显示在 Android 的 Toast 中。
2

评论 (0)

取消