android - 在 Android 上尝试 impl C 库,但应用程序崩溃
问题描述
我想将 C 库添加到我的项目中。lzfse用于通过苹果算法解码 img。
我已将 c 文件添加到项目中
添加了 CmakeLines 文件:
externalNativeBuild {
cmake {
path "src/main/lzfse/CMakeLists.txt"
version "3.10.2"
}
}
我已经为以下内容编写了 JNI decode
:
JNIEXPORT jint JNICALL
Java_com_android_Decompressor_decode(
JNIEnv* env, jclass cls, jobject src, jobject dst
) {
uint8_t* src_buffer = (*env)->GetDirectBufferAddress(env,src);
const size_t src_size = (const size_t) (*env)->GetDirectBufferCapacity(env, src);
uint8_t* dst_buffer = (*env)->GetDirectBufferAddress(env,dst);
size_t dst_size = (size_t) (*env)->GetDirectBufferCapacity(env, dst);
jlong test = lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL);
return (jint) test;
}
然后我从 kt decode fun 调用:
val buf = ByteBuffer.wrap(byteArray)
val buf_out = ByteBuffer.allocateDirect(byteArray.size *20)
val size= decode(dstArray = buf_out, srcArray = buf)
但是我的应用程序崩溃了
2020-02-25 20:12:25.717 28603-28603/com.android A/libc:致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR),tid 28603 () 中的故障地址 0x0,pid 28603 ()
我哪里输了?
解决方案
我已经修复了崩溃!一段时间后,我决定发布工作代码。因此,从项目调用本机 c++:
private val dstArray: ByteBuffer = ByteBuffer.allocateDirect(DESTINATION_BUFFER_CAPACITY)
private val srcArray: ByteBuffer = ByteBuffer.allocateDirect(SRC_BUFFER_CAPACITY)
decode(srcArray.put(byteArray), dstArray)
这里而不是:
val buf = ByteBuffer.wrap(byteArray)
val size= decode(dstArray = buf_out, srcArray = buf)
我通过分配一个直接缓冲区 ByteBuffer.allocateDirect
并将源数组放入缓冲区 srcArray.put(byteArray)
。因为正如@Botje在他的帖子中所说:
包装 ByteArray 不会产生直接缓冲区(至少在 Android 上)。
我的 JNI:
JNIEXPORT JNICALL
Java_com_android_Decompressor_decode(
JNIEnv *env, jclass cls, jobject src, jobject dst
) {
uint8_t *src_buffer = (*env)->GetDirectBufferAddress(env, src);
const size_t src_size = (const size_t) (*env)->GetDirectBufferCapacity(env, src);
uint8_t *dst_buffer = (*env)->GetDirectBufferAddress(env, dst);
size_t dst_size = (size_t) (*env)->GetDirectBufferCapacity(env, dst);
lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL);
}
所以我几乎没有改变JNI。但是在我的第一个代码示例中,我发现一切正常,直到该行:
//...
return (jint) test;
这条线路导致了坠机。
就我而言,我不需要返回值,所以我重写了 JNI 函数而不返回任何值,但我认为可以找到返回值失败的地方。谢谢那些试图提供帮助的人,我希望我的帖子也能对某人有所帮助。
推荐阅读
- javascript - 使用 Browserstack、Selenium Webdriver 和 node.js 图像比较库(看起来相同)进行自动视觉回归
- php - 如何在不刷新的情况下更新竞争,但除了此内容中的一个元素?
- forms - 我应该设计我的 API 来接收 JSON 作为一个层次结构的孩子吗?
- reactjs - 从 ReactJS 中的 props 设置状态时,有没有办法使用变量作为值的一部分?
- python - For each row, count the number of dates that were within 12 months of each other?
- r - 重新投影栅格堆栈列表
- r - 根据定义计算 MSE 与 Var - 偏差
- javascript - 是否可以从另一个类内部调用一个类(不扩展)?
- r - 使用 ggplot 在轴标签下方添加文本
- azure-data-explorer - 有没有办法在 Azure 数据资源管理器中查询所有表的值?