5

I already posted a question regarding it, but at that time I haven't have the account. I got a reply but I was still confused and I cannot continue on that thread.

I am re posting the question again along with a link to previous conversation.

Returning char array from java to string - JNI

The data I am storing in Java is serialized. I make a java function call using following piece of code.

The following code assumes that char of C is compatible with byte of Java, because char of Java is of 2 bytes whereas char of C is of 1 byte. The jbyte is also a signed char*

    //value will be the serialized data
void store(char* key, char* value, int val_len)

{

    //consider the jclass and methodid are already initialized

    jstring j_key = (*env)->NewStringUTF(env, key);
    jbyteArray j_value = (*env)->NewByteArray(env, val_len);

    (*env)->SetByteArrayRegion(env, j_value, 0, val_len, (jbyte *)value);

    //The store method on java side will save the value (as is) in memory
    (*env)->CallStaticVoidMethod(j_class, store_method, key, value);

    (*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, JNI_ABORT);
    (*env)->ReleaseStringUTFChars(env, j_key, key);

}

Once I have saved the data, I use another function to retrieve data from store. At that time i do not know the size of data I am going to retrieve. My API is in C and store is in Java. I will use my C functions to interact with Java. And also there can be multiple threads retrieving data from Java store at same time.

I am making calls from C to Java and my control should return to C program after retrieving data. I am a little confuse on how the code will work. How will I get pointer to array (retrieved from java) and then retrieve it using GetByteArrayElements. Remember I dont know the size of data I am going to retrieve before hand and therefore cannot create a byte array using NewByteArray function and later fill it with data in java code.

2 Answers 2

12

Ok, I figuered it out. I'll put it down here so others can also take advantage of it.

Consider the following java method that returns a byte array (just a dummy code, no checks etc)

public static byte[] GetData(){
    return myStore.getData();
}

and on C side, you can retrieve the byte[] as following

    void get_data()
{       
    int len = 0;
    char* value = NULL;
    /*Consider j_class, and j_methodid are already initialized*/
    jbyteArray j_value = (*env)->CallStaticObjectMethod(env, j_class, j_methodid);

    if(j_value != NULL)
    {
        len = (*env)->GetArrayLength(env, j_value);
        value = (*env)->GetByteArrayElements(env, j_value, NULL);
    }

    /*later on release the resource*/
    (*env)->ReleaseByteArrayElements(env, j_value, value, 0);
}

I have checked it and it works. I am going to check it for 2-D array now. I think it'd be the same as this only you'd be getting jobjectArray and every element of this array is a jbyteArray.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks I've run into the exact same problem and this code was helpful. In VisualStudio I had to include some casts to get it to compile though, I had to cast the return value from CallStaticObjectMethod with (jbyteArray), and I had to cast the return value from GetByteArrayElements with (char *)
Thank you for this! 4 years later I came upon the same problem in the env-> methods not working to read in a byte array field. This solution worked :)
1

Thank you very much! I was trying to pass a double array from C to Java and java in turn returns a renewed double array to C. This is part of JNI where I am trying to link a Java code to Fortran source code. But Fortran code has to call one more Java code for some calculation. So I am doing Java to C to Fortran to C to Java using JNI. Solution to sending a double array from C to Java and Java returning a double array to C is here.

jdoubleArray tempA = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //create an array with 3 elements to be sent to Java
jdoubleArray tempB = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //This is will be //assigned to returned java double array
(*envG)->SetDoubleArrayRegion(envG,tempA,0,3,(const jdouble *)arr);//need to send the //tempA array to Java. "arr" is the double array coming to C from Fortran!
int leng = 0;
for (i = 0; i < 1; i++) {
//sending an array "tempA" to Java. Java returns tempB, a double array
tempB = (*envG)->CallObjectMethod(envG, obj_print, id_print,(*A),(*B),(*C),tempA);
   if (tempB != NULL){
   for (k = 0; k < 3; k++){
      leng = (*envG)->GetArrayLength(envG, tempB);
     jdouble* value = (*envG)->GetDoubleArrayElements(envG, tempB, NULL);
      printf("FROM JAVA ARRAY %f\n", value[k]);
     } //end for
   } //end if

1 Comment

Thanks. Hope it'll help others

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.