JNI dans Netbeans

nasix
JNI dans Netbeans

Bonjour tout le monde,

Je vais utiliser une fonction de C avec du code JAVA, j ai fait une librairie et je l ai appelé via une methode mative JAVA,

le probleme est que Netbeans n arrive pas a trouver la librairie meme si je specifie son adresse ou je la met dans le repertoire des librairies

merci pour vos aides

fredericmazue

A prioiri ce n'est pas Netbeans qui ne trouve pas la librairie, mais la JVM lancée par Netbeans pour démarrer ton application. Tu dois passer une instruction à la JVM au lancement. Pour cela dans Netbeans:

Project properties -> Run -> VM Options

et tu donnes quelques chose comme

-Djava.library.path=repertoire_qui_contient_la_lib

et voilà :)

nasix

Quote:
-Djava.library.path=repertoire_qui_contient_la_lib

Vous etes sur que le nom de l'option est java.library.path, parceque ca ne marche pas.

merci

fredericmazue

Sûr, certain, archi certain, tout cela sans l'ombre d'un demi doute,

La JNI je l'ai manipulé bien des fois et même écrit deux articles sur ce sujet dans Programmez!

Est-ce que dans ta classe java la librairie est chargée au moins ? (je veux dire par ton code Java) Peut être qu'il y a plusieurs problèmes simultanés à régler, peut être qu'il y a un pb de droit d'accès (je crois me souvenir que tu es sous Unix) peut être que plein de choses.

Tu ne montres ici aucun message d'erreur ni aucun code. C'est difficile de t'aider.

nasix

Merci pour votre reponse,

fin je vais donner en detail ce que j ai fait,

je veux juste appeler une fonction runsmv qui affiche un message("utilisation reussie").

voila mon fichier testc.c :

Quote:

#include /* --------- fourni avec le JDK */
#include
#include "testj.h"

JNIEXPORT void JNICALL Java_testj_runsmv(JNIEnv *env, jobject obj){

printf("utilisation reussie");

}

et voila mon code java, testj.java:

Quote:

class testj {

public native void runsmv();

static {
System.load("/home/nasri/JNI/smvlib.so");
}

public static void main(String[] args) {
new testj().runsmv();
}

}

je compile la classe java :

Quote:
javac testj.java

puis je genere le .h :

Quote:
javah -jni testj

juste apres je passe au fichier .c :

Quote:
gcc -c testc.c -I. -I../Logiciel/jdk1.5.0_06/include/ -I../Logiciel/jdk1.5.0_06/include/linux/ -o testc.o

en fin je crée la lib que je nomme smvlib.so :

Quote:
gcc testc.c -shared -o smvlib.so

quand j appelle la classe a partir d une ligne de commande :

java testj

ca marche, mais quand j utilise la librairie a partir d'une autres classe SMV dans netbeans (et j ajoute l option -D... dans run->VM Option) non plus, j aurai l'exception suivante :

Quote:
java.lang.unsatisfiedLinkError : runsmv
fredericmazue

Quote:

j ajoute l option -D...

Moi j'aurais bien aimé savoir exactement ce qu'il a derrière -D
C'est au moment où ça devient le plus intéressant que tu ne dit plus rien.

fredericmazue

Normalement pour toi ça doit être

-Djava.library.path=/home/nasri/JNI

Tu peux aussi faire ça dans ton environnement:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/nasri/JNI

et **relancer** ton netbeans pour que LD_LIBRARY_PATH soit lue

nasix

oui c exactement ce que j ai fait, il apparait qu'il trouve la librairie, le probleme est dans l'utilisation de la fonction, parce que quand je change le nom de la lib(smvlib.o a la place de smvlib.so), il me donne l'exception suivante :

Quote:

Can't load library : smvlib.o

donc c pas un pb de path

nasix

Je veux savoir si je peux utiliser cette librairie par une autre classe exe.java comme suit :

Quote:

public class exe{

public native void runsmv();

static {

System.load("/home/nasri/JNI/smvlib.so");

}

public static void main(String []args){

new exe().runsmv();

}

}

sans recreer la librairie ni de compiler le fichier .c

fredericmazue

Quote:

Je veux savoir si je peux utiliser cette librairie par une autre classe exe.java comme suit

Oui bien sûr. Même si la librairie est chargée dans une classe A, tu peux l'utiliser dans une classe B

fredericmazue

Quote:

le probleme est dans l'utilisation de la fonction

Possible. Je subordore quelque chose. Pour être sûr il faudrait que tu fasses un petit essai: recomplier ta lib C avec la fonction comme ceci

JNIEXPORT void JNICALL Java_testj_runsmv(JNIEnv *env, jobject obj){ 

/* printf("utilisation reussie"); */

} 

Sans le printf autrement dit.

Et tu essaies sous Netbeans. La question est de savoir si oui ou non ça va lever l'exception UnsastifiedLinkError.

Si oui, je ne sais pas où est ton problème.

Si non, ça veut dire qu'à cause de la façon dont Netbeans est lancé, le runtime du C (qui contient printf) n'est pas accessible.

A voir et on en reparle

gaby
meme probleme

Bonjour
je suis rendu au meme point sous netbeans et il semble que meme si j'enleve le printf
dans mon .c j'ai le meme probleme
Si vous avez la solution je suis preneur
merci d'avance

fredericmazue

Devant tant de messages de désespoir, et je dois le dire un peu intrigué, j'ai fait un essai avec du code Jni à moi, sous Netbeans 5.0 et Windows.
Je suis désolé de vous dire que ça fonctionne très bien et évidemment que cela fonctionnera tout aussi bien sous Linux. Ce n'est pas une blague j'affirme que ça fonctionne. J'ai fait comme dit en réponse au post initial, à savoir j'ai défini la propriété java.library.path. c'est à dire que, sous Netbeans et pour mon essai perso, j'ai mis très exactement:

-Djava.library.path=c:\temp\Jni\lib

à VM Options sous Project|Properties|Run

Ma dll native étant déposée dans c:\temp\Jni\lib

Si ça ne marche pas chez vous sans appel à printf (c'est à dire sans appel à un runtime C) sous Netbeans et que ça marche sous le shell, il n'y a qu'une raison: vous vous gourrez en donnant le nom du répertoire sous lequel est déposée votre librairie native.

A Gaby: merci de ne pas me poster en message privé un doublon d'un post sur le forum.

gaby
reponse de desespoir

Bonjour et je te remerci de ta réponse

Je suis sous linux
Le problème est qu'il trouve la lybrari mais qu'il ne trouve pas la fonction
car il me met unsatisfiedlinkerror:"nom_de_la_fonction"
grace à la ligne rajoutée dans les options de la VM il trouve la lybrari car
il ne me met plus unsatisfiedlinkerror:"nom_de_la-lybrari"
je n'arrive pas a mettre le doigt sur la source du problème
j'ai verifié mon URL pour ma lybrari est ok
merci d'avance pour ta reponse

fredericmazue

Alors dans ce cas, c'est que ta librairie est mal construite et que la signautre de la fonction appelée ne correspond pas à ce que cherche la JVM, ou bien la fonction native appelée en appelle une autre inaccessible

gaby
plus de détail

j'ai essayer pas mal de truc dans ce sens comme de spécifier les chemins des libraris
utilisées par ma librari dynamiques mais rien ne marche
Enclenches tu une options particulière dans ton netbeans?
As tu plus de détails sur les problmes que tu viens de me citer et des solutions possibles?
Là je suis vraiment à cours d'idées
merci d'avance.

fredericmazue

Quote:

Enclenches tu une options particulière dans ton netbeans?

Rien en dehors que je que je t'ai dit à toi et aux autres. Simplement le -Djava.library.path=....

Quote:

As tu plus de détails sur les problmes que tu viens de me citer et des solutions possibles?

Bon je reprends une dernière fois pour essayer de clarifier au mieux.

De deux chose l'une.

Soit ça marche sous le shell et pas sous Netbeans. Soit ça ne marche pas du tout, ni sous shell ni sous Netbeans.

Si ça marche sous shell, alors tu te trompes en donnant le java.library.path sous Netbeans. Désolé de te ressortir ça, mais malheureusement il n'y a rien d'autre à dire. Le posteur intiial ayant dit que ça marchait sous shell avec lui, l'affaire était close de mon point de vue.

Si ça ne marche pas non plus sous shell (ce que dans ton cas tu ne précises pas), alors ta librairie native est mal construite. Dans ce cas deux possibilités:

- les fonctions de la librairie ne sont pas exportées, ce qui sous Linux paraît tout simplement impossible.

- Le compilateur C++ utilisé décore les noms de fonction. Décorer ça veut dire qu'en interne il ajoute des infos dans le nom de fonction pour des raisons trop longues à expliquer ici. Par exemple:

mafonction devient xxx25@_mafonction

Du coup la JVM qui essaie de charger mafonction ne la trouve pas dans la lib et lève l'exception qui te fait tant souffrir.

Dans ce cas il faut compiler avec une option qui, soit interdit au compilateur de décorer, soit définit un alias sans décoration dans la librairie. De mémoire avec g++ je dirais qu'il faut compiler avec

--add-stdcall-alias

Mais il faut vérifier en consultant la doc du compilateur bien sûr. D'ailleurs tu n'a pas dit lequel tu utilises.

Voilà tout ce que je peux te dire, et je t'assure qu'il n'y a rien d'autre à dire.

gaby
solution possible

bonjour

je peut enfin t'apporter plus de précision
premièrement j'ai reussit a le faire marcher sous "eclipse" donc je suis plutot content
mais plus encore mon programme marche entierement sous console donc j'en est déduit
que le probleme vient de la façon qu'a netbeans d'ordonner les fichiers et les libraris

J'ai de plus vérifié mon chemin pour mon option VM et il est correct

je pense donc tester ta solution lors de la compilation de mon C
Je te recontacte par la suite pour te dire si ca marche ou pas

merci encore pour ton aide

fredericmazue

Quote:

je pense donc tester ta solution lors de la compilation de mon C

Totalement inutile. Je te l'ai dit si ça marche sous console alors ta librairie native est correctement compilée.
Même chose si ça marche sous eclipse. Donc ça ne sert absolument à **rien** de te prendre la tête avec ça.
Si ça foire sous Netbeans c'est parce que vous faites une bêtise tous autant que vous êtes. Je me demande bien laquelle d'ailleurs.
Ou alors dernière explication possible, ça serait que Netbeans soit buggé et ne passe pas la propriété -Djava.library.path à la JVM qu'il lance, ce qui paraît tout simplement incroyable.

Pour le vérifier, c'est tout simple, au tout début du main de ton programmre Java tu ajoutes cette ligne:

System.out.println(System.getProperty("java.library.path"));

et tu regardes ce que ça sort. Si tu as null alors il y a un problème avec Netbeans lui même. Si tu as autre chose que Netbeans, c'est toi qui a fait une boulette quelque part.

Quote:

que le probleme vient de la façon qu'a netbeans d'ordonner les fichiers et les libraris

Rien à voir. Dd'abord quelle façon particulière il a Netbeans selon toi ?

gaby
reponse

Salut

juste en coup de vent j'ai remarqué que eclipse n'avait pas les .jar
je me trompe peut'-etre
j'essaye cet apres midi ta ligne de commande (la je peut pas) et je te dis ce que ca donne

merci encore

fredericmazue

Quote:

eclipse n'avait pas les .jar

Pardonne moi, mais ça ne veut rien dire ça.

Quote:

ta ligne de commande

Hem, ce n'est pas une ligne de commande.

fredericmazue

Petite précision. j'ai écrit

Quote:

au tout début du main de ton programmre tu ajoutes....

Mais il est bien évident que si ta librairie est chargée dans un bloc static dans la classe principale (je ne sais pas si c'est ton cas car tu n'as pas montré de code) alors c'est dans le bloc static qu'il faut ajouter la ligne, puisqu'un bloc static est exécuté en tout premier:

exemple:

static
{
            System.out.println(System.getProperty("java.library.path"));
            System.loadLibrary("ma_librairie_native");
}
gaby
test

salut

j'ai tester le getProperty et il n'y a pas de probleme il telecharge bien le chemin
mais ca ne marche toujours pas
quand au code j'ai le meme que celui qu'on t'a donné au début de la discussion
je n'est plus d'idée là

merci d'avance

fredericmazue

Quote:

j'ai tester le getProperty et il n'y a pas de probleme il telecharge bien le chemin

Donc ce n'est pas un problème qui vient de Netbeans

Quote:

je n'est plus d'idée là

Et bien moi j'en ai une. Je l'ai eue cet après midi. J'étais en déplacement et en voiture je me demandais ce qui pouvait bien t'arriver. Et tout d'un coup j'ai compris et je me suis dit: Ce n'est pas un problème avec Netbeans c'est un problème avec Gaby. Il me parle en même temps d'une histoire de jar sans aucun sens, "pas pareil avec Eclipse et Netbeans", alors il a voulu incorporer sa dll dans un jar sans jamais le dire dans sa question.

C'est bien ça ?

Seulement voilà, les renseignements que j'ai donnés sont valables pour une librairie native déposée dans un répertoire. Dans REPERTOIRE sur le disque dur, pas dans un jar.