我正在开发一个名为 Galileo 的 Rust 库,使用 FFI 到 Android,并尝试在 Android 模拟器中运行它。
它可以很好地使用命令进行编译,并在您期望的位置生成
x86
目录:
cargo ndk -t i686-linux-android -o ./android_ffi build -p galileo
我使用 UniFFI 创建 Kotlin 绑定,效果很好:
cargo run --bin uniffi-bindgen generate --library target/i686-linux-android/debug/libgalileo.so --language kotlin --out-dir out
然后,我将生成的
x86/libgalileo.so
复制到我的测试 Android 应用程序 jniLibs/x86
中,并将生成的 galileo.kt
添加到 MainActivity.kt
旁边。我还从主要活动的 galileo.kt
中调用一个函数。
然后我添加对 JNA 的依赖:
implementation("net.java.dev.jna:jna:5.14.0")
并将
libjnidispatch.so
添加到 jniLibs/x86
。之后,测试应用程序编译成功,libjnidispatch
被正确加载(我知道,因为在我将编译的库放到正确的位置之前,运行失败并缺少该文件)。但运行时,应用程序会在日志中崩溃:
Process: com.example.myapplication, PID: 4134
java.lang.UnsatisfiedLinkError: Unable to load library 'galileo':
dlopen failed: cannot locate symbol "android_main" referenced by "/data/app/~~BbeW1CYviVt5gyj4KvK3Mw==/com.example.myapplication-gJRCDqgORFGFroidh0hO1w==/base.apk!/lib/x86/libgalileo.so"...
dlopen failed: cannot locate symbol "android_main" referenced by "/data/app/~~BbeW1CYviVt5gyj4KvK3Mw==/com.example.myapplication-gJRCDqgORFGFroidh0hO1w==/base.apk!/lib/x86/libgalileo.so"...
dlopen failed: cannot locate symbol "android_main" referenced by "/data/app/~~BbeW1CYviVt5gyj4KvK3Mw==/com.example.myapplication-gJRCDqgORFGFroidh0hO1w==/base.apk!/lib/x86/libgalileo.so"...
Native library (android-x86/libgalileo.so) not found in resource path (.)
我确信的是:
libgalileo.so
使用正确的目标进行编译libjinidispatch
在它旁边时被正确加载我不明白的是:
android_main
。这个 .so
文件不是二进制文件,不应该运行。我的 Android 或 Rust 项目中没有 adroid_main
。对于 Android,您需要 AAR 而不是 JAR 文件。
implementation("net.java.dev.jna:jna:5.14.0@aar")
来自 JNA 常见问题解答:
要在 Android 上使用 JNA,请将以下依赖项添加到 gradle(请注意 @aar):
compile 'net.java.dev.jna:jna:4.4.0@aar'
如果您使用 Proguard,您还应该将以下内容添加到您的 Proguard 规则:
-dontwarn java.awt.* -keep class com.sun.jna.* { *; } -keepclassmembers class * extends com.sun.jna.* { public *; }