Salut,
oui,
j'ai très bien compris.... et visiblement tu ne cernes pas
vraiment le but de JNI...
Pour
faire simple :
Imagine
que tu as une dll écrite en C/C++ et que tu veuilles
l'utiliser dans ton application java (ce qui est ton cas). Cette DLL
te permet d'afficher un message sur la console (le cas simple d'un
printf), pour l'utiliser tu devras wrapper les fonctions avec JNI,
exemple :
dans
la dll tu as la méthode 'void print(char *str);' qui n'est pas
utilisable tel quelle dans ton application java. Maintenant il te
faut écrire le wrapper, donc commence par la partie java
(exemple avec une classe Print.java):
public
class Print {
static
{
//
demande à la jvm de charger ta librairie,
//
ici tu ne mets que le nom court de la lib (sans l'extension).
System.loadLibrary("Print");
}
//
ici tu précises à la JVM que le comportement de la
méthode sera fait nativement (en C ou C++)
public
native void print(String str);
}
voici
maintenant la classe java pour le test (je parlerai après de
la partie C/C++)
public
class Test {
public
static void main(String ...argv) {
Print
p = new Print();
p.print("Hello
de java\n");
}
}
Pour
exécuter l'application dans un premier temps le mieux est de
mettre l'option '-Djava.library.path=chemin' à la ligne de
lancement sinon, si tu ne veux pas te prendre la tête sous
windoz tu rajoutes la lib dans le système32.
Bref
avant de mettre en place le code C/C++, il te faut demander à
la jvm de te générer un fichier header(.h) associé
à ta classe Print.java, pour ce faire utilise la commande :
javah
-jni -verbose Print
Note
: ici Print n'est autre que le fichier Print.class (pas le .java)
Passons
au code C/C++, ici on fait appel à la fonction printf du C
(vois ça comme la fonction de ta DLL). Tu fais un projet DLL
avec ton IDE (en gros l'utilisation simple de JNI se base sur des DLL
représentant ton wrapper entre le monde java et le monde
C/C++), tu le link avec les fichiers include de la jvm(voir la doc de
ton IDE pour ajouter des includes dans le path) <jdk_version>/include
et <jdk_version>/include/tonOs, enfin tu ajoutes le fichier
Print.h à ton projet :
ton
fichier Print.h devrait ressembler à ça :
/*
DO NOT EDIT THIS FILE - it is machine generated */
#include
<jni.h>
/*
Header for class Print */
#ifndef
_Included_Print
#define
_Included_Print
#ifdef
__cplusplus
extern
"C" {
#endif
/*
* Class: Print
* Method: print
* Signature:
(Ljava/lang/String;)V
*/
JNIEXPORT
void JNICALL Java_Print_print (JNIEnv *, jobject,
jstring);
#ifdef
__cplusplus
}
#endif
#endif
maintenant
tu codes le fichier Print.c (pourquoi pas) en lui indiquant le dll
main (c'est la faute à windoz si il faut même un 'main'
dans une DLL)
Note:
ici je ne vais pas brider l'exemple à windoz donc tu peux
faire abstraction aux '#ifdef' et '#endif'.
#include
<stdio.h>
#include
"Print.h"
//
notre dll main
#ifdef
WIN32
#include
<windows.h>
bool
WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID
lpvReserved){
return
TRUE;
}
#endif
/*
* Def du comportement de
la méthode java
* Class: Print
* Method: print
* Signature:
(Ljava/lang/String;)V
*/
JNIEXPORT
void JNICALL Java_Print_print (JNIEnv *env, jobject jprint, jstring
jstr) {
//variables
pour la copie de la chaine java vers C/C++
const
char *utf_string;
jboolean
isCopy;//pour tester si la copie est bonne ou non
//copie
de la chaine java
utf_string
= (*env)->GetStringUTFChars(env, jstr, &isCopy);
//affichage
de la chaine passée depuis java
printf("%s",
utf_string);
//si
la copie c'est bien passée alors on libère les
ressources
if(isCopy
== JNI_TRUE)
(*env)->ReleaseStringUTFChars(env,
jstr, utf_string);
}
ATTENTION:
JNIEnv ne s'utilise pas de la même façon en C et en C++,
exemple :
en
C tu fais :
(*env)->GetStringUTFChars(env,
jstr, &isCopy);
or
en C++ tu fais :
env->GetStringUTFChars(jstr,
&isCopy);
Maintenant
si tu veux des exemples plus complets, regarde dans les sources que
j'ai déposé sur ce site (il y en à 3 je crois
qui utilises du JNI à différents niveaux)
------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."
OoWORAoO