0
votes

I want to add C library to my project. lzfse for decode img via apple algorithm.

I have added c files to project

added CmakeLines file:

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

I have written JNI for 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;
}

then I call from kt decode fun:

 val buf = ByteBuffer.wrap(byteArray)

            val buf_out = ByteBuffer.allocateDirect(byteArray.size *20)
            val size= decode(dstArray = buf_out, srcArray = buf)

But My app just crashes

2020-02-25 20:12:25.717 28603-28603/com.android A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 28603 (), pid 28603 ()

Where did I lose?

2
@Nick the question is about where I wrong when adding the librarySerg Burlaka

2 Answers

1
votes

Wrapping a ByteArray does not result in a direct buffer (at least on Android). You will need to call GetByteArrayElements to get a (possibly copied) pointer.

1
votes

I have fixed the crash! After some time I have decided to publish the working code. So, the call native c++ from project:

  private val dstArray: ByteBuffer = ByteBuffer.allocateDirect(DESTINATION_BUFFER_CAPACITY)
  private val srcArray: ByteBuffer = ByteBuffer.allocateDirect(SRC_BUFFER_CAPACITY)

 decode(srcArray.put(byteArray), dstArray)

Here instead of:

 val buf = ByteBuffer.wrap(byteArray)
 val size= decode(dstArray = buf_out, srcArray = buf)

I allocate a direct buffer via ByteBuffer.allocateDirect and put the source array in buffer srcArray.put(byteArray). Because as @Botje said in his post :

Wrapping a ByteArray does not result in a direct buffer (at least on Android).

my 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);

}

So I almost haven't changed JNI. But in my first code sample, I have found that all works until the line:

  //...
  return (jint) test;

The line caused the crash.

In my case, I didn't need return value so I rewrite JNI function without return any values, but I think it possible to find where I have failed with the return value. Thanks, guys who tried to give some help, I hope my post also can be helpful for someone.