2009-08-05 5 views
5

J'ai déjà posté une question à ce sujet, mais je n'ai pas encore de compte à ce moment-là. J'ai eu une réponse mais j'étais encore confus et je ne peux pas continuer sur ce fil.Récupération d'un tableau d'octets de longueur inconnue à partir du magasin Java

Je répète la question avec un lien vers la conversation précédente.

Returning char array from java to string - JNI

Les données que je suis le stockage en Java est sérialisé. Je fais un appel de fonction java en utilisant le morceau de code suivant.

Le code suivant suppose que char de C est compatible avec octet de Java, car char de Java est de 2 octets alors que char de C est de 1 octet. Le jbyte est aussi un 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); 

}

Une fois que je l'ai enregistré les données, j'utiliser une autre fonction pour récupérer les données du magasin. À ce moment-là, je ne connais pas la taille des données que je vais récupérer. Mon API est en C et le magasin est en Java. J'utiliserai mes fonctions C pour interagir avec Java. Et il peut également y avoir plusieurs threads qui récupèrent des données du magasin Java en même temps.

Je fais des appels de C vers Java et mon contrôle devrait retourner au programme C après avoir récupéré des données. Je suis un peu confus sur la façon dont le code va fonctionner. Comment vais-je obtenir un pointeur vers un tableau (récupéré à partir de Java) et ensuite le récupérer en utilisant GetByteArrayElements. Rappelez-vous que je ne connais pas la taille des données que je vais récupérer avant ma main et que je ne peux donc pas créer un tableau d'octets en utilisant la fonction NewByteArray et plus tard le remplir avec des données en code java.

Répondre

12

Ok, je l'ai illustré. Je vais le mettre ici afin que les autres puissent aussi en profiter.

Tenir compte de la méthode java suivante qui retourne un tableau d'octets (juste un code fictif, aucun contrôle, etc.)

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

et sur le côté C, vous pouvez récupérer l'octet [] comme suit

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

Je l'ai vérifié et cela fonctionne. Je vais vérifier pour le tableau 2-D maintenant. Je pense que ce serait la même chose que ce que vous obtiendriez jobjectArray et chaque élément de ce tableau est un jbyteArray.

+0

Merci J'ai rencontré exactement le même problème et ce code a été utile. Dans VisualStudio j'ai dû inclure quelques moulages pour le compiler, j'ai dû convertir la valeur de retour de CallStaticObjectMethod avec (jbyteArray), et j'ai dû convertir la valeur de retour de GetByteArrayElements avec (char *) –

+0

Merci pour ça! 4 ans plus tard, je suis tombé sur le même problème dans les méthodes env-> ne travaillant pas à lire dans un champ tableau d'octets. Cette solution a fonctionné :) – blkhatpersian

1

Merci beaucoup! J'essayais de passer un double tableau de C à Java et java renvoie à son tour un double tableau renouvelé à C. Cela fait partie de JNI où j'essaye de lier un code Java au code source de Fortran. Mais le code Fortran doit appeler un code Java supplémentaire pour certains calculs. Je fais donc Java en C pour Fortran en C to Java en utilisant JNI. La solution pour envoyer un tableau double de C vers Java et Java retournant un tableau double en C est ici.

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 
+0

Merci.J'espère que ça va aider les autres – ata

Questions connexes