Rust 语言 实现 Android NDK 原生模块 Rust 编写 JNI 接口

Rust阿木 发布于 3 天前 5 次阅读


Rust 语言实现 Android NDK 原生模块(JNI 接口)开发指南

随着移动应用的日益普及,跨平台开发变得越来越重要。Rust 语言因其高性能、安全性和并发特性,逐渐成为跨平台开发的热门选择。Android NDK(Native Development Kit)允许开发者使用 C/C++ 语言编写原生模块,以实现高性能的代码。本文将介绍如何使用 Rust 语言结合 Android NDK 来开发原生模块,并通过 JNI(Java Native Interface)与 Java 代码交互。

环境准备

在开始之前,请确保以下环境已经准备就绪:

1. 安装 Rust 语言和 Cargo 包管理器。
2. 安装 Android Studio 和 NDK。
3. 设置好 Android 开发环境,包括 SDK 和模拟器。

创建 Rust 项目

使用 Cargo 创建一个新的 Rust 项目:

sh
cargo new rust_ndk_module
cd rust_ndk_module

编写 Rust 代码

在 `src/lib.rs` 文件中,我们将定义一个简单的原生模块,该模块将提供一个方法供 Java 代码调用。

rust
use std::os::raw::{c_char, c_void};

[no_mangle]
pub extern "C" fn get_greeting() -> const c_char {
let greeting = "Hello from Rust!";
std::ffi::CString::new(greeting).unwrap().into_raw()
}

[no_mangle]
pub extern "C" fn free_greeting(ptr: const c_char) {
unsafe {
if !ptr.is_null() {
std::ffi::CString::from_raw(ptr);
}
}
}

在这段代码中,我们定义了两个函数:

1. `get_greeting`:返回一个指向静态字符串的指针。
2. `free_greeting`:释放由 `get_greeting` 返回的字符串指针。

配置 Cargo

为了使 Rust 代码能够在 Android NDK 环境中编译,我们需要修改 `Cargo.toml` 文件:

toml
[package]
name = "rust_ndk_module"
version = "0.1.0"
edition = "2021"

[dependencies]

[build-dependencies]
cc = "1.0"

[profile.release]
rustflags = ["-C", "link-arg=-s", "-C", "link-arg=--strip-all"]

[profile.dev]
rustflags = ["-C", "link-arg=-s", "-C", "link-arg=--strip-all"]

这里我们添加了 `cc` 依赖,用于调用 C 编译器,并设置了 `rustflags` 以优化编译后的二进制文件。

编译 Rust 代码

使用以下命令编译 Rust 代码:

sh
cargo build --target aarch64-linux-android

这将生成一个名为 `librust_ndk_module.so` 的动态库文件。

创建 JNI 接口

在 Android 项目中,我们需要创建一个 JNI 接口来调用 Rust 模块。

1. 在 `src/main/java/com/example/rust_ndk_module/RustModule.java` 文件中,添加以下代码:

java
package com.example.rust_ndk_module;

public class RustModule {
static {
System.loadLibrary("rust_ndk_module");
}

public native String getGreeting();
}

2. 在 `CMakeLists.txt` 文件中,添加以下代码以链接 Rust 动态库:

cmake
find_library(
log-lib
log
)

add_library( Sets the name of the library.
rust_ndk_module

Sets the library as a shared library.
SHARED

Provides a relative path to your source file(s).
src/main/cpp/rust_module.cpp )

target_link_libraries( Specifies the target library.
rust_ndk_module

Links the target library to the log library
included in the NDK.
${log-lib} )

add_library( Sets the name of the library.
rust_ndk_module_swig

Sets the library as a shared library.
SHARED

Provides a relative path to your source file(s).
src/main/cpp/rust_module.cpp )

target_link_libraries( Specifies the target library.
rust_ndk_module_swig

Links the target library to the log library
included in the NDK.
${log-lib} )

add_library( Sets the name of the library.
rust_ndk_module_rust

Sets the library as a shared library.
SHARED

Provides a relative path to your source file(s).
src/main/cpp/rust_module.cpp )

target_link_libraries( Specifies the target library.
rust_ndk_module_rust

Links the target library to the log library
included in the NDK.
${log-lib} )

add_library( Sets the name of the library.
rust_ndk_module_rust
SHARED
src/main/cpp/librust_ndk_module.so )

target_link_libraries( Specifies the target library.
rust_ndk_module_rust

Links the target library to the log library
included in the NDK.
${log-lib} )

3. 在 `src/main/AndroidManifest.xml` 文件中,添加以下权限:

xml

测试 JNI 接口

现在,我们可以通过以下代码测试 JNI 接口:

java
package com.example.rust_ndk_module;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("rust_ndk_module");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

RustModule rustModule = new RustModule();
String greeting = rustModule.getGreeting();
System.out.println(greeting);
}
}

运行应用,你应该能在控制台中看到来自 Rust 模块的问候语。

总结

本文介绍了如何使用 Rust 语言结合 Android NDK 来开发原生模块,并通过 JNI 与 Java 代码交互。通过以上步骤,你可以轻松地将 Rust 代码集成到 Android 应用中,以实现高性能的模块。随着 Rust 语言的不断发展,其在移动开发领域的应用将越来越广泛。