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 :

Librairie static incluse dans librairie dynamique


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2003
    Messages
    223
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2003
    Messages : 223
    Par défaut Librairie static incluse dans librairie dynamique
    Bonjour,

    J'ai créer une librairie qui utilise les librairie tinyxml et libjpeg.
    Ayant seulement envie d'intégrer et de distribué ma librairie j'ai decidé de faire la chose suivant:

    Je compile tinyxml en static
    Je compile libjpeg en static

    Puis je compile malib en dynamic en incluant les versions deux autres librairies:

    Sous MinGW les commandes pour linker donnent:

    C:\MinGW\bin\ar.exe cr ..\lib\libtinyxml.a tinystr.cpp.obj tinyxml.cpp.obj \tinyxmlerror.cpp.obj tinyxmlparser.cpp.obj
    C:\MinGW\bin\ranlib.exe ..\lib\libtinyxml.a

    meme chose pour jpeg

    C:\MinGW\bin\gcc.exe -shared -o bin\malib.dll -Wl,--out-implib,lib\malib.dll.a -Wl,--major-image-version,1,--minor-image-version,0 obj1.o obj2.o obj3.o 3rdparty\lib\liblibjpeg.a 3rdparty\lib\libtinyxml.a

    Au final quand je créer mon programme je doit utiliser:

    C:\MinGW\bin\g++.exe -Wall main.cpp.obj -o bin\AdVisOr.exe -Wl,--out-implib,lib\libAdVisOr.dll.a -Wl,--major-image-version,0,--minor-image-version,0 lib\malib.dll.a 3rdparty\lib\liblibjpeg.a 3rdparty\lib\libtinyxml.a

    alors que j'aimerais ne pas avoir a inclure 3rdparty\lib\liblibjpeg.a 3rdparty\lib\libtinyxml.a, car du coup cela me désavantage de devoir inclure de nouveaux les librairies static.

    Je ne trouve pas grand chose sur le Web et j'utilise Cmake pour la compilation.

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Tout simplement parce que tu as exporté des éléments de tes deux librairies statiques dans l'interface de ta librairie dynamique... Du coup, un programme utilisant la DLL doit linker aussi avec les librairies statiques pour réussir à trouver tous les symboles.

    Typiquement, c'est mettre dans un entête de classe un attribut qui est défini dans une librairie statique (=> demande à faire une classe intermédiaire et/ou du cast sauvage avec void*) et/ou du code (toujours dans le .H) utilisant directement les fonctions de la librairie statique (=> les mettre dans le .CPP).

    Tu as aussi la farce quand ton compilateur exporte par défaut TOUTES les fonctions de la DLL, au lieu de se limiter à celles définies explicitement. Là, faut voir la doc du compilo pour savoir comment empêcher l'exportation d'un symbole dans une DLL.

    Il te faut :
    • Vérifier ce que ta DLL exporte actuellement (via Dependancy Walker), afin de repérer l'élément posant problème.
    • Repenser ton interface DLL de façon à n'exposer QUE tes propres fonctions / classes, en MASQUANT l'implémentation / utilisation des éléments des deux librairies statiques.
      Ceci implique un remaniement lourd de tes entêtes, l'utilisation de classes plus génériques qui seront les seules réellement exportées, l'utilisation de "void*" à outrance avec casts internes pour masquer le type réel de l'implémentation, ...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2003
    Messages
    223
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2003
    Messages : 223
    Par défaut
    Oky, merci

    donc si j'utilise des fonctions de tinyxml dans ma libraires et dans mon programmes j'ai intérêt a l'utiliser en tant que shared, ou directement inclure le code dans malib.dll.

    Par contre si j'arrive a cacher libjpeg c'est mieux de le compiler en statique et de le cacher dans malib.

    c'est bien ca ?

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Je vais prendre un exemple, ce sera plus clair...

    Voici par exemple un bout du code d'une librairie statique :
    Code Private.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <........>
     
    // Structure de contrôle utilisée partout dans la librairie pour toutes les fonctions, comme l'est "FILE*" pour l'accès aux fichiers.
    typedef struct {
     ....
     ....
     ....
    } private_handle ;
    Ce code est censé, à priori, rester "planqué" et non visible depuis ta DLL.

    Or, imaginons que tu as un entête public de ta DLL construit ainsi :
    Code Public.h : 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
    #include "Private.h" // pour "private_handle"
    
    class Bidule {
    
      // Ouverture d'une ressource. La valeur de retour est passé à toutes les méthodes de la classe, MAIS L'UTILISATEUR NE LA MANIPULE JAMAIS DIRECTEMENT.
      // La méthode met à jour l'attribut m_PrivateHandle de la classe.
      bool Open ( .... ) ;
    
      // Travail effectif.
      int Process ( ..... ) ;
    
      // Fermeture.
      bool Close ( void ) ;
    
    private:
      private_handle* m_PrivateHandle ;
    
    } ;

    Problème : private_handle fait partie de la librairie statique, devrait être privé, et est utilisé par une classe publique via un attribut... Du coup, pour pouvoir compiler, tu dois inclure l'entête de la librairie statique, qui va bien entendu forcer un link de cette librairie statique au sein de ton exécutable, alors que tu croyais n'utiliser que ta DLL !!

    Pour corriger, tu devras faire ainsi :
    Code Public.h : 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
    // On supprime le #include public vers la librairie statique.
    
    class Bidule {
    
      // Ouverture d'une ressource. La valeur de retour est passé à toutes les méthodes de la classe, MAIS L'UTILISATEUR NE LA MANIPULE JAMAIS DIRECTEMENT.
      // La méthode met à jour l'attribut m_PrivateHandle de la classe.
      bool Open ( .... ) ;
    
      // Travail effectif.
      int Process ( ..... ) ;
    
      // Fermeture.
      bool Close ( void ) ;
    
    private:
      void* m_MaskedPrivateHandle ;  // Passage en void*
    
    } ;
    Code Public.cpp : 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
    #include "Public.h"
    #include "Private.h" // pour "private_handle", il passe donc dans le CPP.
     
    bool Bidule::Open ( .... ) {
     
      private_handle* m_PrivateHandle ;
     
      // Reste de la fonction.
     
      // Affectation de l'attribut avec cast.
      m_MaskedPrivateHandle = static_cast<void*>(m_PrivateHandle) ;
    }
     
    int Bidule::Process ( ..... ) {
     
      // Via un cast, on récupère le handle "normalement", avec l'ancien nom d'attribut pour éviter d'avoir à modifier inutilement le code déjà écrit.
      private_handle* m_PrivateHandle = static_cast<private_handle*>(m_MaskedPrivateHandle) ;
     
      // Corps de la fonction, inchangé désormais.
    }
     
    ...
    Ainsi, même si la DLL continue d'utiliser la librairie statique, cela n'est pas visible de l'extérieur, et aucun entête de la librairie statique n'est requis. Du coup, ton exécutable n'aura plus besoin d'être linké avec la librairie statique en question...


    Tu vois mieux de quoi je veux parler ?
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #5
    Membre confirmé
    Inscrit en
    Juin 2003
    Messages
    223
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2003
    Messages : 223
    Par défaut
    Oky, parfait ...
    merci pour l'aide

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Je pense que Mac y va un peu fort....

    Si ton entete est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct mallibprivatestruct;
    class DLL_EXPORT DeMaLib
    {
        private:
          malibprivatestruct*   m_pStruct;
    };
    Personne (utilisateur) n'a besoin d'avoir la définition de malibprivatestruct, juste celle d'un pointeur !

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

Discussions similaires

  1. [Librairies] Inserer lignes dans fichier RTF
    Par tit_oune dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 04/05/2012, 10h21
  2. [WIN32][D2005] Integrer une librairie C/C++ dans Delphi
    Par ZeGothMan dans le forum Langage
    Réponses: 8
    Dernier message: 30/03/2006, 13h56
  3. Inclusion de librairie sous visual
    Par petdelascar dans le forum C
    Réponses: 11
    Dernier message: 07/12/2005, 20h39
  4. Réponses: 5
    Dernier message: 25/04/2004, 00h57
  5. Inclusion de librairie ratée
    Par glop - pas glop dans le forum MFC
    Réponses: 21
    Dernier message: 15/02/2004, 18h41

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