Search code examples
javacjava-native-interface

How to cast a char* to jbyteArray in JNI whitout malloc a new memory area


I have a code mixed Java and C, I need pass a byte[] of Java code to C code to complete some calculate.I convert byte[] to char* by using below code in JNI(env is JNIEnv * of C):

jboolean is_copy = JNI_TRUE;
char *native_byte_array = (char *) (*env)->GetByteArrayElements(env, byte_array, &is_copy);

I finished calculate with type char* and the return value has type char* too,I want to return a value with jbyteArray so I can use it in type byte[] in Java.I have try the below code in JNI(env is JNIEnv * of C):

jbyteArray java_buffer = (*env)->NewByteArray(env, buffer_size);

(*env)->SetByteArrayRegion(env, java_buffer, 0, buffer_size, (const jbyte *) native_buffer);

It seems like that NewByteArray will create a new byte[] instance and SetByteArrayRegion will copy data into the new created byte[]. However,it's not efficient if I have a big return value that need to be cast to byte[]. So,is there a way that can create a jbyteArray instance without malloc new memory and make it point to the char* area?


Solution

  • You could use NewDirectByteBuffer. (I know, it's not the same as a byte[], but it comes quite near) To return:

    //Do something...
    char* result=...;
    return (*env)->NewDirectByteBuffer(env, result, buffer_size);
    

    To pass:

    JNIEXPORT jobject JNICALL Java_Foo_bar(JNIEnv* env,jclass cls, jobject buffer){
      char* bufferPassedFromJava=(*env)->GetDirectBufferAddress(env,buffer);//May return NULL
    }
    

    These DirectByteBuffers are, simplified just a small wrapper around a long (The address), so you can use them without copying arrays around