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 :

Echec lors du didacticiel JNI de Java


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 11
    Par défaut Echec lors du didacticiel JNI de Java
    Bonjour,

    En cherchant sur le net un guide pour apprendre JNI, je suis tombé sur une page officielle de JAVA. Je ne pouvais pas rêver mieux, donc...
    http://java.sun.com/developer/online.../jniexamp.html

    Le tuto décrit un programme qui lit le contenu d'un fichier et l'affiche dans la console.
    La lecture du fichier est fait en C, et l'affichage, et JAVA.

    Le guide me dit de créer 3 fichiers: ReadFile.java, Readfile.h (généré par javah), et Readfile.cpp

    Readfile.java
    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
    import java.util.*;
     
    public
    class ReadFile {
     
    	//Native method declaration
    	native byte[] loadFile( String name );
     
    	//Load the library
    	static {
    		System.loadLibrary( "nativelib" );
    	}
     
    	public static
    	void
    	main( String args[] ) {
     
    		byte buf[];
     
    		// Create class instance
    		ReadFile mappedFile = new ReadFile();
     
    		// Call native method to load ReadFile.java
    		buf = mappedFile.loadFile( "ReadFile.java" );
     
    		//Print contents of ReadFile.java
    		for( int i=0;i < buf.length;i++ ) {
    			System.out.print( (char)buf[ i ] );
    		}
    	}
    }
    ReadFile.h
    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
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class ReadFile */
     
    #ifndef _Included_ReadFile
    #define _Included_ReadFile
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    /*
     * Class:     ReadFile
     * Method:    loadFile
     * Signature: (Ljava/lang/String;)[B
     */
    JNIEXPORT jbyteArray JNICALL
    Java_ReadFile_loadFile( JNIEnv*,
                            jobject,
                            jstring );
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif
    ReadFile.cpp
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    #include <jni.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
     
    JNIEXPORT jbyteArray JNICALL
    Java_ReadFile_loadFile( JNIEnv*  env,
                            jobject  jobj,
                            jstring  name ) {
     
    	caddr_t     m;
    	jbyteArray  jb;
    	jboolean    iscopy;
     
    	struct stat finfo;
     
    	const char *mfile = (*env)->GetStringUTFChars( env,
    	                                               name,
    	                                               &iscopy );
     
    	int fd = open( mfile,
    	               O_RDONLY );
     
    	if( fd == -1 ) {
    		printf( "Could not open %s\n",
    		        mfile );
    	}
     
    	lstat( mfile,
    	       &finfo );
     
    	m = mmap( (caddr_t) 0,
    	          finfo.st_size,
    	          PROT_READ,
    	          MAP_PRIVATE,
    	          fd,
    	          0 );
     
    	if( m == (caddr_t) - 1 ) {
    		printf( "Could not mmap %s\n",
    		        mfile );
     
    		return( 0 );
    	}
     
    	jb = (*env)->NewByteArray( env,
    	                           finfo.st_size);
     
    	(*env)->SetByteArrayRegion( env,
    	                            jb,
    	                            0, 
    	                            finfo.st_size,
    	                            (jbyte *)m );
     
    	close( fd );
     
    	(*env)->ReleaseStringUTFChars( env,
    	                               name,
    	                               mfile );
     
    	return ( jb );
    }

    J'ai installé MinGW sur Windows, et je dispose de GCC.

    Donc, à la commande:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    cl -Ic:/jdk1.2/include 
       -Ic:/jdk1.2/include/win32 
       -LD nativelib.c -Felibnative.dll
    ... j'ai plutôt fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    gcc -Wall -shared ReadFile.cpp -o nativelib.dll -I"c:\Program Files\Java\jdk1.6.0_11\include" -I"c:\Program Fil
    es\Java\jdk1.6.0_11\include" -L"c:\Program Files\Java\jdk1.6.0_11\lib"
    là-dessus, la console m'affiche des centaines de pages d'erreurs. Voici la fin, pour vous donnez une idée.

    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
    58
    59
    60
     
    ...
    ...
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1822: error: 'const struct JNINativeInterface_' has no member named 'DeleteWeakGlobalRef'
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h: In member function `jboolean JNIEnv_::ExceptionCheck()':
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1826: error: 'const struct JNINativeInterface_' has no member named 'ExceptionCheck'
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h: In member function `_jobject* JNIEnv_::NewDirectByteBuffer(void*, int)':
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1830: error: 'const struct JNINativeInterface_' has no member named 'NewDirectByteBuffer'
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h: In member function `void* JNIEnv_::GetDirectBufferAddress(_jobject*)':
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1833: error: 'const struct JNINativeInterface_' has no member named 'GetDirectBufferAddress'
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h: In member function `jobjectRefType JNIEnv_::GetObjectRefType(_jobject*)':
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1839: error: 'const struct JNINativeInterface_' has no member named 'GetObjectRefType'
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h: At global scope:
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1851: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1853: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1859: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1877: error: `JNICALL' has not been declared
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1877: error: ISO C++ forbids declaration of `jint' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1877: error: `jint' declared as function returning a function
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1877: error: ISO C++ forbids declaration of `DestroyJavaVM' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1879: error: `JNICALL' has not been declared
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1879: error: ISO C++ forbids declaration of `jint' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1879: error: `jint' declared as function returning a function
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1879: error: ISO C++ forbids declaration of `AttachCurrentThread' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1879: error: `int JNIInvokeInterface_::jint(int*)' and `int JNIInvokeInterface_::jint(int*)' cannot be
     overloaded
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1881: error: `JNICALL' has not been declared
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1881: error: ISO C++ forbids declaration of `jint' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1881: error: `jint' declared as function returning a function
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1881: error: ISO C++ forbids declaration of `DetachCurrentThread' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1881: error: `int JNIInvokeInterface_::jint(int*)' and `int JNIInvokeInterface_::jint(int*)' cannot be
     overloaded
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: `JNICALL' has not been declared
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: `jint' is not a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: ISO C++ forbids declaration of `jint' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: ISO C++ forbids declaration of `version' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: `jint' declared as function returning a function
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: ISO C++ forbids declaration of `GetEnv' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1883: error: `int JNIInvokeInterface_::jint(int*)' and `int JNIInvokeInterface_::jint(int*)' cannot be
     overloaded
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1885: error: `JNICALL' has not been declared
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1885: error: ISO C++ forbids declaration of `jint' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1885: error: `jint' declared as function returning a function
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1885: error: ISO C++ forbids declaration of `AttachCurrentThreadAsDaemon' with no type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1885: error: `int JNIInvokeInterface_::jint(int*)' and `int JNIInvokeInterface_::jint(int*)' cannot be
     overloaded
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1892: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1895: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1898: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1902: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1905: error: `jint' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1916: error: `JNIIMPORT' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1919: error: `JNIIMPORT' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1922: error: `JNIIMPORT' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1926: error: `JNIEXPORT' does not name a type
    c:/Program Files/Java/jdk1.6.0_11/include/jni.h:1929: error: expected constructor, destructor, or type conversion before "void"
    ReadFile.cpp:3:21: sys/ipc.h: No such file or directory
    ReadFile.cpp:4:21: sys/shm.h: No such file or directory
    ReadFile.cpp:5:22: sys/mman.h: No such file or directory
    ReadFile.cpp:10: error: `JNIEXPORT' does not name a type
    Je ne sais pas où se situe mon erreur... est-ce dans la ligne de commande de compilation, dans la configuration des mes PATHS..?

    Ce doit être une erreur facile à régler pour qui a déjà travaillé avec JNI.

    Dans le cas où un expert JNI passerait dans les parages, j'aimerais lui demander ce qui, selon lui, vaut la peine d'être externalisé dans un code C/C++, et ce qui n'en vaut pas la peine.

    Merciiiii

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 11
    Par défaut
    J'ai simplifié le problème en éditant un programme bien plus simple, qui toutefois ne fonctionne toujours pas.
    J'ai rassemblé les fichiers dans un fchier ZIP:testJNI.zip, pour que vous puissiez tester vous-même.

    L'archive contient 3 fichiers:

    testJNI.java
    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
    public
    class TestJNI {
     
    	static {
    		System.loadLibrary( "jnidll" );
    	}
     
    	public static native
    	String
    	onePlusOne();
     
    	public static
    	void
    	main( String args[] ) {
     
    		System.out.println( onePlusOne() );
    	}
     
    }
    testJNI.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <jni.h>
     
    /*
     * Class:     TestJNI
     * Method:    onePlusOne
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL
    Java_TestJNI_onePlusOne( JNIEnv*  env,
                             jclass   jClass ) {
     
    	return (*env)->NewStringUTF( env, "2" );
    }
    compile.cmd
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    javac TestJNI.java
    javah -jni TestJNI
    gcc -I"c:\Program Files\Java\jdk1.6.0_07\include" -I"c:\Program Files\Java\jdk1.6.0_07\include\win32" -c TestJNI.c
    gcc -shared -o jnidll.dll TestJNI.o
    Vous l'aurez compris, je lance compile.cmd pour simplifier la compilation.

    L'effet est le même. Quand je lance "java TestJNI", l'erreur suivante s'affiche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Exception in thread "main" java.lang.UnsatisfiedLinkError: TestJNI.onePlusOne()Ljava/lang/String;
            at TestJNI.onePlusOne(Native Method)
            at TestJNI.main(TestJNI.java:12)

  3. #3
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    J'avais fait quelques tests avec JNI, et j'ai été obligé d'utiliser l'option -Wl,--kill-at lors de la génération de la DLL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -shared -Wl,--kill-at -o jnidll.dll TestJNI.o
    C'est propre à Windows et au mode d'appel stdcall qui rajoute un suffixe sur les noms de fonctions, ce qui fait que JNI ne les reconnait pas. Cette option permet d'éviter cela...

    Source : --kill-at

    a++

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 11
    Par défaut
    Super, ça fonctionne.
    Je ne suis pas une brutasse en compilation C/C++, mon travail m'a orienté vers d'autres langages.
    Votre réponse me fait gagner du temps. J'allais chercher un utilitaire pour décortiquer la DLL créée afin de m'assurer de la présence des méthodes implémentées, je serais tombé sur ce constat, et je serais revenu pour embêter pour savoir d'où ça pouvait provenir.

    merci beaucoup adiGuba

Discussions similaires

  1. [JNI]dll java
    Par icepower dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 03/09/2009, 14h53
  2. Echec de chargement de l'Applet java
    Par nada83 dans le forum Applets
    Réponses: 2
    Dernier message: 19/05/2006, 18h16
  3. [JNI]Employer Java dans C++
    Par dinver dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 29/12/2005, 21h09
  4. Réponses: 3
    Dernier message: 24/01/2005, 11h57
  5. Echec lors de la connexion à la base de données.
    Par mclown dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 26/10/2004, 23h36

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