【问题标题】:Try impl C library on Android but app crashes在 Android 上尝试 impl C 库,但应用程序崩溃
【发布时间】:2023-03-31 13:23:01
【问题描述】:

我想将 C 库添加到我的项目中。 lzfse通过苹果算法解码img。

我已将 c 文件添加到项目中

添加了 CmakeLines 文件:

externalNativeBuild {
    cmake {
        path "src/main/lzfse/CMakeLists.txt"
        version "3.10.2"
    }
}

我已经为decode写了JNI:

 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 ()

我在哪里输了?

【问题讨论】:

标签: android android-ndk java-native-interface decode


【解决方案1】:

包装 ByteArray does not result in a direct buffer(至少在 Android 上)。 您需要调用 GetByteArrayElements 来获取(可能复制的)指针。

【讨论】:

  • 感谢@Botje 的帮助。正如你所说的Wrapping a ByteArray does not result in a direct buffer 。所以我为我的源分配了一个直接缓冲区。
【解决方案2】:

我已经修复了崩溃!一段时间后,我决定发布工作代码。 所以,从项目中调用native 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 在他的post 中所说:

包装 ByteArray 不会产生直接缓冲区(至少在 安卓)。

我的 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 函数而不返回任何值,但我认为可以找到返回值失败的地方。 谢谢那些试图提供帮助的人,我希望我的帖子也能对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 2023-02-14
    • 2017-12-23
    • 1970-01-01
    相关资源
    最近更新 更多