How to debug Rust libraries in Android application with Vs code LLDB
⚓ Rust 📅 2025-12-15 👤 surdeus 👁️ 4rust library
lib.rs ---define add、multiply function
#[no_mangle]
pub extern "C" fn add(left: u64, right: u64) -> u64 {
left + right
}
#[no_mangle]
pub extern "C" fn multiply(left: u64, right: u64) -> u64 {
left * right
}
pub mod ffi;
android_jni.rs ---define jni ffi
#![cfg(target_os = "android")]
use jni::objects::JClass;
use jni::sys::{jint, jlong, JNI_VERSION_1_6, JavaVM};
use jni::JNIEnv;
use std::os::raw::c_void;
#[no_mangle]
#[allow(non_snake_case)]
fn catch_unwind_to_java<F>(env: &mut JNIEnv, f: F) -> Option<jlong>
where
F: FnOnce() -> jlong,
{
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
Ok(v) => Some(v),
Err(_) => {
throw_runtime_exception(env, "panic in rustcall native code");
None
}
}
}
/// Throw a Java `RuntimeException` with the given message.
fn throw_runtime_exception(env: &mut JNIEnv, msg: &str) {
// Best-effort: if throwing fails, there's not much else we can do.
let _ = env.throw_new("java/lang/RuntimeException", msg);
}
/// JNI: `public static native long add(long left, long right);`
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_com_example_rustcall_RustCall_add(
mut env: JNIEnv,
_class: JClass,
left: jlong,
right: jlong,
) -> jlong {
catch_unwind_to_java(&mut env, || crate::add(left as u64, right as u64) as jlong).unwrap_or(0)
}
pub extern "system" fn Java_com_example_rustcall_RustCall_multiply(
mut env: JNIEnv,
_class: JClass,
left: jlong,
right: jlong,
) -> jlong {
catch_unwind_to_java(&mut env, || crate::multiply(left as u64, right as u64) as jlong)
.unwrap_or(0)
}
mod.rs
// Platform-specific exports.
//
// IMPORTANT: each module is strictly gated via `cfg(...)` so that building for Android
// does not even compile iOS/OHOS code (and vice versa).
// Android JNI exports (enable with `--features android-jni`).
#[cfg(all(target_os = "android"))]
pub mod android_jni;
// iOS exports (C ABI; for Swift/ObjC you typically generate a header).
#[cfg(target_os = "ios")]
pub mod ios;
// HarmonyOS / OpenHarmony exports.
// NOTE: Rust `target_os` values for OHOS/OpenHarmony differ by toolchain; rather than
// using unknown `target_os = "..."`
// (which triggers `unexpected_cfgs` warnings), we gate this with:
// - a feature flag, and
// - explicit exclusion of Android/iOS so those builds never compile OHOS code.
#[cfg(all(not(target_os = "android"), not(target_os = "ios")))]
pub mod ohos;
Compilation command
cargo ndk -t arm64-v8a -t armeabi-v7a -t x86 -t x86_64 -o ./jniLibs build --release
Android Demo
Rust Call
package com.example.rustcall;
public final class RustCall {
static {
System.loadLibrary("rustcall");
}
private RustCall() {}
public static native long add(long left, long right);
public static native long multiply(long left, long right);
}
build.gradle.kts
android {
...
buildTypes {
debug {
// Debug 构建:保持可调试 & 不混淆(方便 Java/Kotlin + Native 调试)
isMinifyEnabled = false
isDebuggable = true
// 允许调试 native so(Android Studio/LLDB attach native 需要)
isJniDebuggable = true
// Debug 构建下:保留打进 APK 的所有 .so 的符号信息(覆盖所有 ABI)
packaging {
jniLibs {
keepDebugSymbols += setOf("**/librustcall.so")
}
}
}
release {
isMinifyEnabled = false
isDebuggable = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
// Debug 构建下:保留打进 APK 的所有 .so 的符号信息(覆盖所有 ABI)
packaging {
jniLibs {
keepDebugSymbols += setOf("**/librustcall.so")
}
}
}
}
...
}
So how should I debug it?
1 post - 1 participant
🏷️ Rust_feed
