tags:

views:

494

answers:

1

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  A: 

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.

cornerback84
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 *)
Graphics Noob