IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

[JNI]Conversion de chemin java->C++


Sujet :

Entrée/Sortie Java

  1. #1
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Points : 722
    Points
    722
    Par défaut [JNI]Conversion de chemin java->C++
    Bonjour,

    Je dois interfacer une dll avec mon appli Java, et je rencontre quelques soucis avec les chemins de fichiers contenant des accents.
    Au départ, j'utilisais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    env->GetStringUTFChars(path,0);
    où env correspond à un JNIEnv* et path est une jstring.

    Malheureusement les accents ne passe pas en UTF-8 (par exemple "é" devient 'A-tilde'+'sigle copyright' : code ASCII : #195 et #169)
    J'ai trouvé ceci dans une doc sur JNI, mais ça ne fonctionne pas vraiment tel quel et je n'arrive pas à l'adapter :
    8.2.2 Translating jstrings to Native Strings
    Use the String.getBytes method to convert a jstring to the appropriate native
    encoding. The following utility function translates a jstring to a locale-specific
    native C string:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
    {
         jbyteArray bytes = 0;
         jthrowable exc;
         char *result = 0;
         if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
              return 0; /* out of memory error */
         }
         bytes = (*env)->CallObjectMethod(env, jstr, MID_String_getBytes);
         exc = (*env)->ExceptionOccurred(env);
         if (!exc) {
              jint len = (*env)->GetArrayLength(env, bytes);
              result = (char *)malloc(len + 1);
              if (result == 0) {
                   JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
                   (*env)->DeleteLocalRef(env, bytes);
                   return 0;
              }
              (*env)->GetByteArrayRegion(env, bytes, 0, len,
              (jbyte *)result);
              result[len] = 0; /* NULL-terminate */
         } else {
              (*env)->DeleteLocalRef(env, exc);
         }
         (*env)->DeleteLocalRef(env, bytes);
         return result;
    }
    Quelqu'un aurait-il déjà rencontré ce genre de problème?
    Sinon, si vous voyez comment adapter le code, je suis preneur aussi...

    Pour l'instant, j'ai fait ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    char* JNU_GetStringNativeChars(JNIEnv* env, jstring jstr) {
    	jbyteArray bytes = 0;
    	//MODIF : test avec ExceptionCheck au lieu de ExceptionOccured (pas reconnu) => plus besoin de exc 
    //	jthrowable exc;
    	char* result = 0;
     
    	if (env->EnsureLocalCapacity(2) < 0) {
    		return 0;  // out of memory error
    	}
     
    	//MODIF : redéfinition de MID_String_getBytes qui n'est pas connu apparemment
    	jclass cls = env->GetObjectClass(jstr);
    //	jmethodID mid = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
    	jmethodID MID_String_getBytes = env->GetMethodID(cls, "getBytes", "(Ljava/lang/String;)[B");
     
     
    	//MODIF : casté pour que ça marche...
    //	bytes = env->CallObjectMethod(jstr, MID_String_getBytes);
    	bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes);
     
    	byte bytesC[] = env->GetByteArrayElements(bytes,0);
     
    //	printf("%d\n", bytes->)
    	//MODIF : test avec ExceptionCheck au lieu de ExceptionOccured. (pas reconnu)..
    //	exc = env->ExceptionOccured();
    	jboolean exc = env->ExceptionCheck();
     
    	if (!exc) {
    		printf("pas d'exception\n");
    		jint len = env->GetArrayLength(bytes);
    		result = (char*)malloc(len+1);
    		if (result == 0) {
    			JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
    			env->DeleteLocalRef(bytes);
     
    			return 0;
    		}
    		env->GetByteArrayRegion(bytes, 0, len, (jbyte*)result);
    		result[len] = 0; // NULL-terminate
    	}
    	else {
    	//MODIF : test avec ExceptionCheck au lieu de ExceptionOccured (pas reconnu) => plus besoin de exc
    		printf("Exception occured...\n");
    //		env->DeleteLocalRef(exc);
    	}
    	env->DeleteLocalRef(bytes);
     
    	return result;
    }

  2. #2
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Points : 722
    Points
    722
    Par défaut
    J'oubliais de préciser que avec ma version modifiée, la méthode me retourne "NULL" (avec un paramètre path qui est différent de null évidemment)
    Et je rentre dans le "else" qui m'affiche "Exception occured"...

  3. #3
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Points : 722
    Points
    722
    Par défaut
    Ok, après avoir bataillé ferme, j'ai trouvé les 3 lignes de code qui me manquaient pour y arriver, alors en cadeau, je vous refourgue la solution gratos
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    char* JNU_GetStringNativeChars(JNIEnv* env, jstring jstr) {
    	//!!!!! C'est ces définitions qu'il me manquait...
    	jclass Class_java_lang_String = env->FindClass("java/lang/String");
    	jmethodID MID_String_getBytes = env->GetMethodID(Class_java_lang_String, "getBytes", "()[B");
     
     
    	jbyteArray bytes = 0;
    	//on utilise ExceptionCheck au lieu de ExceptionOccured => plus besoin de exc 
    //	jthrowable exc;
    	char* result = 0;
     
    	if (env->EnsureLocalCapacity(2) < 0) {
    		return 0;  // out of memory error
    	}
     
    	//casté pour que ça marche...
    	bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes);
     
    	//on utilise ExceptionCheck au lieu de ExceptionOccured...
    //	exc = env->ExceptionOccured();
    	jboolean exc = env->ExceptionCheck();
     
    	if (!exc) {
    		jint len = env->GetArrayLength(bytes);
    		result = (char*)malloc(len+1);
    		if (result == 0) {
    			JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
    			env->DeleteLocalRef(bytes);
     
    			return 0;
    		}
    		env->GetByteArrayRegion(bytes, 0, len, (jbyte*)result);
    		result[len] = 0; // NULL-terminate
    	}
    	else {
    		//on utilise ExceptionCheck au lieu de ExceptionOccured => plus besoin de exc
    		printf("Exception occured...\n");
    //		env->DeleteLocalRef(exc);
    	}
    	env->DeleteLocalRef(bytes);
     
    	printf("JNU_GetStringNativeChars => %s\n", result);
     
    	return result;
    }
     
     
    void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
    	jclass cls = env->FindClass(name);
    	/* if cls is NULL, an exception has already been thrown */
    	if (cls != NULL) {
    		env->ThrowNew(cls, msg);
    	}
    	/* free the local ref */
    	env->DeleteLocalRef(cls);
    }
    Voilà! En espérant que ça évite à certains de s'arracher les cheveux comme moi...

  4. #4
    Membre habitué

    Inscrit en
    Février 2007
    Messages
    250
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Février 2007
    Messages : 250
    Points : 162
    Points
    162
    Par défaut
    Merci BEAUCOUP d'avoir publié la solution du problème que tu avais toi-même posté, peux de gens le font.
    Juste pour dire que ça marche très bien. J'ai pas testé les fuites mémoires mais je fais confiance à ton code.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Chemin JAVA sous Linux
    Par PM_calou dans le forum Langage
    Réponses: 13
    Dernier message: 29/08/2007, 11h31
  2. [FEDORA] Chemin JAVA 1.6
    Par PM_calou dans le forum RedHat / CentOS / Fedora
    Réponses: 5
    Dernier message: 17/06/2007, 13h15
  3. Conversion de chemins vers DOS.
    Par JM_Cholet dans le forum Windows
    Réponses: 2
    Dernier message: 12/12/2006, 15h00
  4. Conversion CCSID en java
    Par sniper91 dans le forum DB2
    Réponses: 2
    Dernier message: 20/06/2006, 13h27
  5. Chemin Java
    Par LordBob dans le forum Applications et environnements graphiques
    Réponses: 7
    Dernier message: 01/04/2006, 02h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo