# 【Rust NDK】动态注册和所有权间的纠纷 站点:答源(https://www.dandroid.cn/) 原文:https://www.dandroid.cn/archives/22378 Canonical:https://www.dandroid.cn/archives/22378 作者:技术信源组 发布日期:2024-10-05 最后更新:2026-11-06 18:51 分类:技术方案 内容类型:post 说明:本页是原文的纯文本镜像,供大模型与检索器完整读取;不含导航、广告、付费框。引用请以上方「原文」链接为准。 ## 正文 引言 前面几篇文章基本上将 jni-rs 介绍完了。然而,还有一个较为重要的部分没说明,也就是动态注册。毕竟是可以投入生产的东西了,动态注册这么重要的东西怎么能少?C/C++有的东西,我Rust也得有!那么,开撸! 开发环境 操作系统:Windows 11 编码软件:Visual Studio Code 1.93.1 | Android Studio Ladybug | 2024.2.1 Beta 1 正文 本文将对 ndk 在 rust 中的动态注册进行介绍,并且将重点说明这过程中 所有权 转移的情况。 创建Rust项目 老样子,我们正常创建一个 example_5 的lib项目,然后改造它。 接着,打开 lib.rs 开始编码。 和C/C++一样 jni-rs 也提供了 JNI_OnLoad 函数,接受两个参数。 然后,我们按照常规写法,将 jvm 存起来(第14行)。 这里使用的是Rust提供的 OnceLock 它支持多线程安全,并且只允许赋值一次,读取多次。 读取方式在第20行。 最后,返回 JNI_VERSION_1_6 (值得注意的是,当返回 JNI_VERSION_1_8 时app会崩溃)。 动态注册 当准备工作完毕后,就可以实现上面的 //todo 了。 以下,就是动态注册的实现。 上图,第一个红色框我们将 env 改为了可变的变量,然后增加了第二个红框中的代码。 在第三个红色框中,使用NativeMehtod结构体来表示它是一个本地方法,而它的第三个值fn_ptr需要是一个C函数的指针表示,所以这里的 native_method 函数被强转为了C指针。 我们打开它的实现,可以看到它也有相关说明,第二个值类型就决定了该动态注册的方法是否为 静态的,当类型为 JClass 时就表示该方法是静态方法,当类型为 JObject 时就表示该方法为实例方法。 OK,Rust层到这儿就结束了。 编译出so文件后,我们就可以创建Android项目进行测试了。 cargo ndk -t armeabi-v7a -t arm64-v8a -o ./jniLibs build --release 创建Android项目 然后跑一下,看一下效果。 所有权导致崩溃 果然,前面顺风顺水(前面的几篇文章只要是通过了Rust的编译检查,在Android这边基本上是直接跑起来的),现在呢,总算是遭到报应了。 那么,就需要重新打包,并导出符号表查看崩溃情况了。 直接运行一下 cargo ndk 发现它提供了一个命令行参数 --no-strip。 修改一下编译so的命令。 cargo ndk --no-strip -t armeabi-v7a -t arm64-v8a -o ./jniLibs build --release 重新编译覆盖进android项目后,再来查看崩溃情况。 诶,出现了。从截图看在报错列表中,只有 native_method 这个方法是我们自己写的,那么原因就是它咯。 可这个就是一个简单创建字符串的方法呀,正当我百思不得其解时,问了问AI。 这才恍然大悟,原来是 借用 出现了问题。 被动态注册的 native_method 实际上是直接与jvm进行交互的,所以jvm传入的env实参应该是所有权的转移而并不是可变or不可变的引用 ,因此当我使用 env: &mut JNIEnv 或 mut env: JNIEnv --- 由 答源 DAN 底座 1.4.1 生成 · 2026-11-15T17:15:49+00:00