2017-05-10 2 views
-3

pourquoi faire une boucle foor une fois sur le côté jni et une autre côté java? Est-il possible de retourner juste le tableau sans boucle?jni retourne le tableau de chaînes de c/C++ 11 et l'utilise sur java sans pour la boucle sur le côté C++?

JNIEXPORT jobjectArray JNICALL Java_main_returndays(JNIEnv *env, jobject jobj) 
{ 

    char *days[]={"Sunday", 
       "Monday", 
       "Tuesday", 
       "Wednesday", 
       "Thursday", 
       "Friday", 
       "Saturday"}; 

    jstring str; 
    jobjectArray day = 0; 
    jsize len = 7; 
    int i; 

    day = (*env)->NewObjectArray(env,len,(*env)->FindClass(env,"java/lang/String"),0); 

    for(i=0;i<7;i++)//// without this loop ? 
    { 
    str = (*env)->NewStringUTF(env,days[i]); 
    (*env)->SetObjectArrayElement(env,day,i,str); 
    } 

return day; 
} 
+0

Avez-vous essayé d'utiliser 'while?' – user2079303

+0

pour la boucle ou tandis que la boucle c'est la même chose, juste la condition différente –

Répondre

1

Pour renvoyer une chaîne [] à Java via JNI, vous devez créer le tableau, puis convertir et mettre chaque chaîne dans le tableau. Il n'y a pas de raccourci comme passer le char ** à Java.

Toutefois ... si votre objectif est d'éviter de créer des chaînes Java en C++ via JNI, et de le faire en Java, vous pouvez le faire. Il y a parfois de bonnes raisons de le faire. Dans notre logiciel, nous transmettons des structures de données complexes de C++ à Java. Nous avons constaté que l'utilisation de JNI pour construire les structures de données est très lente (les appels de méthode JNI sont comme 1000 cycles d'horloge chacun). Il est souvent plus rapide de sérialiser en un tableau d'octets en C++, de créer un seul tableau d'octets JNI, de le transmettre à Java via la limite JNI et de désérialiser le tableau d'octets. Je ne vais pas vous donner un exemple de travail complet, mais ça va quelque chose comme ça. Je vais construire un tableau d'octets en C++ qui a des valeurs nulles entre chaque chaîne, puis le passer à Java pour le processus dans une liste (plus facile que String []).

C++:

// Find overall length with nulls 
int len = 0; 
for (int i = 0; i < sizeof(days)/sizeof(char*); i++) { 
    len += strlen(days[i]) + 1; 
} 
// Fill C++ byte array 
char* cBytes = new char[len]; 
char* ptr = cBytes; 
for (int i = 0; i < sizeof(days)/sizeof(char*); i++) { 
    strcpy(ptr, days[i]); 
    ptr += strlen(days[i]) + 1; 
} 
// Copy C++ to Java 
jbyteArray jBytes = env->NewByteArray(len); 
env->SetByteArrayRegion(jBytes, 0, len, cBytes); 
delete [] cBytes; 
return jBytes; 

Java:

byte jBytes[] = // call C++ via JNI 
List<String> strs = new ArrayList<>(); 
int offset = 0; 
// break byte array at null, convert to String 
while (offset < jBytes.length) { 
    for (int i = offset; true; i++) { 
     if (jBytes[i] == 0) { 
     // Default code page assumed. You could also pass a Charset. 
     strs.add(new String(jBytes, offset, i - offset)); 
     offset = i + 1; 
     break; 
     } 
    } 
} 

Je me rends compte qu'il existe des moyens "encore plus optimale" des réseaux passant entre C++ et Java, impliquant généralement une sorte d'emballage NativeByteBuffer. Mais ces méthodes ont souvent des cas particuliers et sont plus complexes.

+0

thx pour votre effort et idée –