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

C++ Discussion :

[JNI] Erreur d'exécution de ma librairie


Sujet :

C++

  1. #1
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut [JNI] Erreur d'exécution de ma librairie
    Bonjour

    Bien que cette question comporte certes le tag JNI (interafaçage Java Natif), ma question porte plus sur mon code C++ de ma librairie.
    Voici mon problème. J'ai écrit une librairie C++ et je veux pouvoir, avec un code Java, soumettre et récupérer des données àcette librairie. C'est plus pour la récupération que mon problème intervient. Je dispose d'un fichier C++ avec le header suivant :
    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
     
    #ifndef FINDPRIMERS_H_
    #define FINDPRIMERS_H_
     
    #include <string>
    #include "PrimersResults.h"
     
    struct Arguments
    {
      long int MinWin, MaxWin, MinTm, MaxTm, MaxDiffTm, MinGC, MaxGC, MinAmp, MaxAmp;
      double MinDeltaGH;
      std::string FileName, FileTheo;
     
      void Usage() const;
      bool Init(int argc, const char* argv[]);
      Arguments(int argc, const char* argv[]);
    };
     
    extern PrimersResults pResults;
     
    void SearchPrimers(PrimersResults& results, TSetSeq& SetSeq, TSetSeq& TheoSeq, long int MinWin, long int MaxWin, long int MinTm, long int MaxTm, long int MinGC, long int MaxGC, double MinDeltaGH, long int Type);
    void FindPrimers(int nb, const char *words[]);
     
    #endif /*FINDPRIMERS_H_*/
    Voici le code C++ qui interroge la librairie et qui renvoit un résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include "FindPrimers.h"
    #include "Main.h"
     
    JNIEXPORT jlong JNICALL Java_Main_getLine (JNIEnv *env, jobject object, jint a, jobjectArray string) {
    		const char *args[a];
    		for (int i=0; i<a; i++){
    			jstring jstr = (jstring)env->GetObjectArrayElement(string, i);
    			args[i] = env->GetStringUTFChars(jstr, 0);
    		}
    		FindPrimers(a, args);
    		//return (jlong)pResults.nb_primers;
    		return 2;
    }
    Or à l'exécution, j'obtiens l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    java.lang.UnsatisfiedLinkError: /home/dbourgais/Snippets/C-C++/MyLibraries/libPCR.so: /home/dbourgais/Snippets/C-C++/MyLibraries/libPCR.so: undefined symbol: pResults
    Ce qui me semble bizarre c'est qu'à la compilation, je n'ai pas d'erreur ni de warning !
    Pourquoi alors ne reconnait-il pas pResults ?

    Merci d'avance de vos réponses.

    @++

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tu n'aurais pas oublié de définir pResults, dans un fichier .cpp ?

  3. #3
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut
    Salut Loulou24, et bravo pour ton avatar de Noel

    J'ai supprimé dans FindPrimers.cpp la définition PrimersResults pResults; étant donné qu'on la trouve dans le header de ce fichier. Etait-ce si important ? Sinon, j'avoue humblement ne pas être ceinture noire de C++ !

    @++

  4. #4
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut
    Entre parenthèses, voici la déclaration de ma classe PrimersResults :
    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
     
    #ifndef PRIMERSRESULTS_H_
    #define PRIMERSRESULTS_H_
     
    #include "TSetBox.h"
     
    class PrimersResults {
     
            public:
                    long int nb_primers;
                    TSetBox SetBox;
                    PrimersResults();
                    ~PrimersResults();
     
            protected:
     
            private:
     
    };
     
    #endif /*PRIMERSRESULTS_H_*/
    @++

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Bon, je vais essayé d'être clair pour un ceinture marron alors.

    pResult dans ton code est une variable globale.
    Comme toute variable globale, il faut qu'elle soit définie. C'est à dire qu'il faut que le compilateur alloue une case mémoire de la taille d'un PrimersResult pour stocker la valeur de pResult.

    Quand tu déclares dans un fichier source "extern PrimersResults pResult", tu dis explicitement au compilateur "N'alloue pas de mémoire pour la variable pResult, la mémoire sera allouée dans une autre unité de compilation.". C'est l'éditeur de lien qui justement fera le lien entre cette variable est l'endroit où elle est stockée.
    Cependant, si cette variable est déclarée 'extern' partout, l'espace pour la stockée ne sera réservé nulle part. Chaque unité de compilation (fichier source si tu préfères) compilera correctement, mais l'éditeur de lien se plaindra.

    Comme le tout est dans une bibliothèque, il n'y a pas d'édition de lien (pour compiler la bibliothèque) donc tu ne vois pas le problème de suite. En revanche, dès que tu veux lier la bibliothèque à autre chose pour en faire une application, le problème apparaît.

    Pour faire bref, et arrêter de me la raconter, le message de l'éditeur de lien est exactement la traduction de ton problème. pResults n'est défini nulle part.
    Une solution rapide et sale: "prend UN seul de tes fichiers source" et déclare pResult sans le mot-clef 'extern'
    Une meilleure solution, regarde dans la FAQ (peut-être), ou fait une recherche sur les variable globale en C++, tu verras qu'on ne fait jamais comme tu procèdes justement, pour les problèmes que tu rencontres.

  6. #6
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut
    Merci VoidSeer de ta réponse, mais j'ai beaucoup de mal à la comprendre.
    Apparemment, l'utilisation d'extern est à prohiber mais je ne vois pas alors comment déclarer et utiliser pResults sur tous mes codes .
    Désolé de ne pas trop comprendre.

    @++

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    C'est un peu compliquer à expliquer en détail sur un forum. Pour vraiment comprendre le pourquoi de ton erreur, il faut comprendre comment marche le stockage des données en C++. J'essaie d'être un peu plus clair.

    Quand on construit une application en C/C++, chaque fichier source (pas les .h, .hpp, etc.) est compilé séparément.
    Je prend l'exemple d'une variable de type Scooter, que j'appelle monScoot.
    Quand tu déclares dans un fichier (attention pas de 'extern ici)
    Il se passe deux choses:
    - La variable monScoot est déclarée, suite à cette déclaration, on peut s'en servir dans le reste de CE fichier source sans provoquer d'erreur de syntaxe ou autre
    - L'espace pour ranger la valeur de pResult est réservé
    En gros, quand le compilateur tombe sur une déclaration de ce genre en plus de savoir que monScoot, c'est un Scooter. Il me construit le garage pour le ranger.
    Je peux changer de scooter, mais c'est toujours dans le même garage que je le range.

    Si dans deux fichiers sources différents tu fais cette déclaration (ta première erreur),
    alors je me retrouve avec deux garages pour le même scooter, d'où le 'multiple définition' que tu obtenais puisque par jeu d'inclusion cette déclaration était présente dans tout tes fichiers sources.

    Quand tu déclares
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    extern Scooter monScoot
    le comportement est différent. Tu indiques au compilateur que monScoot, ça représente un Scooter, mais (grâce au extern) tu lui dis aussi que son garage existe déjà, donc il est inutile d'en créer un autre. C'est l'éditeur de lien qui se chargera de retrouver où est le garage.

    Maintenant, si dans tous les fichiers sources où tu utilises la variable 'monScoot' tu la déclares comme 'externe'. A aucun moment tu ne construis de garage pour la ranger.
    Dans chaque fichier source séparément, on pense que le garage existe, alors on ne s'inquiète pas. Mais à l'édition de liens, on se rend compte qu'il n'existe nulle part où ranger le scoot.

    Ainsi, il faut que dans UN fichier source, ce foutu garage soit créé. C'est à dire qu'il faut que la décalration ne soit pas 'extern', une et une seule fois.

  8. #8
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut
    Ok, VoidSeer, j'ai réfléchi (quel exploit !) à ce que tu m'as dit. J'ai donc fait transiter ma méthode JNIEXPORT jlong JNICALL Java_Main_getLine (JNIEnv *env, jobject object, jint a, jobjectArray string) vers le fichier C++ où j'initialise pResults. Et là, ô miracle, ça marche. D'où une nécessité de centralisation ? A moins qu'il n'y ait plus subtil. Je met donc le thread en Résolu mais je suis ouvert à toutes suggestions.

    @++

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Plus subtil, je ne sais pas. Mais plus simple sûrement.
    Le plus simple serait de se passer de pResult. A quoi cette variable te sert-elle ?

  10. #10
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut
    Cette variable est en fait un container de résultats dans lequel je stocke les résultats de mes analyses. Le programmeur qui avait fait cette librairie à l'origine, se contentait de les afficher à la volée.

    @++

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Alors tu peux facilement modifier ta solution pour que lorsque l'on déclanche les calculs, au lieu d'appeler une fonction qui ne retourne rien et modifie une variable globale, on appelle une fonction qui retourne le conteneur avec les résultats dedans.
    Du coup, plus de variable globale, plus de soucis.

  12. #12
    Expert confirmé
    Avatar de GLDavid
    Homme Profil pro
    Service Delivery Manager
    Inscrit en
    Janvier 2003
    Messages
    2 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Service Delivery Manager
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 867
    Points : 4 873
    Points
    4 873
    Par défaut
    Ok, je vais essayé de voir et étudier cela.
    Merci à toi pour ton aide immense et ta pédagogie.

    @++

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

Discussions similaires

  1. [JNI] Erreur d'exécution pour le système
    Par GLDavid dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 17/03/2006, 15h49
  2. [CR8][VB6] Erreur d'exécution 20533
    Par pvava dans le forum SDK
    Réponses: 1
    Dernier message: 01/02/2005, 11h27
  3. Erreurs d'exécution sous delphi 5
    Par nkd dans le forum Langage
    Réponses: 3
    Dernier message: 06/11/2004, 18h25
  4. [Apache Perl] Erreur à l'exécution de mes cgi
    Par GLDavid dans le forum Apache
    Réponses: 4
    Dernier message: 28/08/2004, 21h23
  5. [Débutant][JNI]Erreur de chargement de dll
    Par Agifem dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 24/04/2003, 15h36

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