Rust NDK宏库ndk-macro的使用,简化Android NDK开发的Rust宏工具
Rust NDK宏库ndk-macro的使用,简化Android NDK开发的Rust宏工具
ndk-macro是实现属性过程宏main的实现,该宏直接应用于主函数。
此宏在ndk-glue中重新导出。通常,不需要直接依赖此库!
用法
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
pub fn main() {
println!("hello world");
}
属性宏支持可选的输入属性:
backtrace = "on|full"
:通过设置RUST_BACKTRACE环境变量启用回溯ndk_glue = "path::to::ndk_glue"
:覆盖默认路径到ndk_glue cratelogger(...props)
:使用传递的配置配置android记录器(需要logger功能):level = "error|warn|info|debug|trace"
:更改记录器的日志级别tag = "my-tag"
:为记录器分配标签filter = "filtering-rules"
:更改默认过滤规则
完整示例demo
// Cargo.toml依赖配置
// [dependencies]
// ndk-glue = "0.3.0"
// 主函数使用ndk_glue::main宏
#[cfg_attr(target_os = "android", ndk_glue::main(
backtrace = "on", // 启用回溯功能
logger( // 配置日志记录器
level = "info", // 设置日志级别为info
tag = "rust-app" // 设置日志标签
)
))]
pub fn main() {
// Android平台上的入口点
println!("Hello from Rust on Android!");
// 这里可以添加你的Android NDK逻辑
// 例如调用JNI接口、处理Android事件等
}
// 另一个使用自定义ndk_glue路径的示例
#[cfg_attr(target_os = "android", ndk_glue::main(
backtrace = "full", // 启用完整回溯
ndk_glue = "my_custom_path::to::ndk_glue", // 自定义ndk_glue路径
logger(
level = "debug", // 调试级别日志
tag = "custom-app", // 自定义标签
filter = "my_app=debug" // 自定义过滤规则
)
))]
pub fn main() {
println!("Custom Android NDK application");
// 应用程序逻辑
}
1 回复
Rust NDK宏库ndk-macro:简化Android NDK开发的Rust宏工具
介绍
ndk-macro是一个专为简化Rust与Android NDK交互而设计的宏库。它通过提供一系列过程宏,帮助开发者更轻松地创建JNI接口、处理类型转换和管理Android生命周期,显著减少模板代码量。
主要功能
- 自动生成JNI绑定代码
- 简化Rust与Java/Kotlin的类型转换
- 提供Android生命周期管理宏
- 支持异步任务处理
安装方法
在Cargo.toml中添加依赖:
[dependencies]
ndk-macro = "0.3"
ndk = "0.7"
使用示例
1. 基本JNI函数声明
use ndk_macro::jni_fn;
#[jni_fn("com.example.rustlib.RustBridge")]
pub extern "C" fn add_numbers(env: JNIEnv, obj: JObject, a: i32, b: i32) -> i32 {
a + b
}
2. 自动类型转换
use ndk_macro::java_string;
#[jni_fn("com.example.rustlib.StringUtils")]
pub extern "C" fn concatenate_strings(
env: JNIEnv,
obj: JObject,
str1: JString,
str2: JString
) -> JString {
let s1: String = java_string!(env, str1);
let s2: String = java_string!(env, str2);
let result = format!("{}{}", s1, s2);
env.new_string(result).unwrap()
}
3. 异步任务处理
use ndk_macro::async_jni;
#[async_jni("com.example.rustlib.AsyncOperations")]
pub async fn fetch_data_async(url: String) -> Result<String, String> {
// 异步网络请求实现
Ok("Data fetched successfully".to_string())
}
4. 生命周期管理
use ndk_macro::android_lifecycle;
#[android_lifecycle]
pub struct DataProcessor {
cache: HashMap<String, String>,
}
impl DataProcessor {
pub fn new() -> Self {
Self {
cache: HashMap::new(),
}
}
pub fn process_data(&mut self, key: String, value: String) {
self.cache.insert(key, value);
}
}
完整示例demo
// 导入必要的库和宏
use ndk_macro::{jni_fn, java_string, async_jni, android_lifecycle};
use jni::JNIEnv;
use jni::objects::{JObject, JString};
use std::collections::HashMap;
// 示例1: 基本数学运算函数
#[jni_fn("com.example.rustlib.MathUtils")]
pub extern "C" fn multiply_numbers(
env: JNIEnv,
obj: JObject,
a: i32,
b: i32
) -> i32 {
// 简单的乘法运算
a * b
}
// 示例2: 字符串处理函数
#[jni_fn("com.example.rustlib.StringUtils")]
pub extern "C" fn to_uppercase(
env: JNIEnv,
obj: JObject,
input: JString
) -> JString {
// 使用java_string!宏转换JString到Rust String
let rust_str: String = java_string!(env, input);
// 转换为大写
let result = rust_str.to_uppercase();
// 创建新的Java字符串并返回
env.new_string(result).unwrap()
}
// 示例3: 异步数据处理函数
#[async_jni("com.example.rustlib.AsyncProcessor")]
pub async fn process_data_async(
data: String
) -> Result<String, String> {
// 模拟异步处理
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
// 返回处理结果
Ok(format!("Processed: {}", data))
}
// 示例4: 生命周期管理结构体
#[android_lifecycle]
pub struct DataManager {
data_store: HashMap<String, Vec<String>>,
}
impl DataManager {
pub fn new() -> Self {
Self {
data_store: HashMap::new(),
}
}
// 添加数据到管理器
pub fn add_data(&mut self, key: String, value: String) {
self.data_store
.entry(key)
.or_insert_with(Vec::new)
.push(value);
}
// 获取数据
pub fn get_data(&self, key: &str) -> Option<&Vec<String>> {
self.data_store.get(key)
}
}
// 主模块测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_multiply_numbers() {
// 测试数学函数
assert_eq!(multiply_numbers(2, 3), 6);
}
#[test]
fn test_data_manager() {
// 测试数据管理器
let mut manager = DataManager::new();
manager.add_data("test".to_string(), "value".to_string());
assert!(manager.get_data("test").is_some());
}
}
配置说明
在android模块的build.gradle中添加:
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
}
}
}
}
最佳实践
- 使用
#[jni_fn]
宏标注所有需要暴露给Java/Kotlin的函数 - 利用
java_string!
宏处理字符串类型转换 - 对于耗时操作,使用
#[async_jni]
实现异步接口 - 通过
#[android_lifecycle]
管理有状态组件的生命周期
注意事项
- 确保Android NDK版本与ndk-macro兼容
- 在Cargo.toml中正确配置ndk版本
- 处理JNI异常时使用提供的错误处理宏
这个宏库大大简化了Rust在Android平台上的集成工作,让开发者能够更专注于业务逻辑的实现。