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

Langage C++ Discussion :

Inclusion et d'une bibliothèque


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut Inclusion et d'une bibliothèque
    Bonjour tout le monde,

    J'ai un problème d'architecture. C'est le suivant :
    • j'ai une classe A -> je généré une bibliothèque A
    • J'ai une classe B qui génère une bibliothèque B et qui utilise la bibliothèque A.


    J'aimerais fournir à un client une bibliothèque B qu'il puisse utiliser juste avec le header de B.
    Est-ce possible dans le cas suivant (ClasseA.h, ClasseA.cpp, ClasseB.h, ClasseB.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #pragma once
    namespace NameSpaceA {
        class ClasseA
        {
        public:
            ClasseA();
            ~ClasseA();
        };
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include "stdafx.h"
    #include "ClasseA.h"
    namespace NameSpaceA {
        ClasseA::ClasseA(){}
        ClasseA::~ClasseA(){}
      }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #pragma once
    using namespace NameSpaceA;
    namespace NameSpaceB {
        class ClasseB
        {
        public:
            ClasseB();
            ~ClasseB();
            ClasseA test(void);
        };
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include "stdafx.h"
    #include "../ClasseA/ClasseA.h"
    #include "ClasseB.h"
    using namespace NameSpaceA;
    namespace NameSpaceB {
        ClasseB::ClasseB(){}  
        ClasseB::~ClasseB(){}    
        ClasseA ClasseB::test(void)    {return ClasseA();} 
    }
    Dans ce cas précis, j'arrive à générer les .lib. Cependant lors de l'utilisation de la librairie B dans un programme quelconque


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int main()
    {
     
        ClasseB();
        std::cout << "Hello World!\n";
    }
    la compilation ne se réalise pas.

    Comment est -ce que je peux générer un {ClasseB.h , ClasseB.lib] autosuffisant ?

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Qu'entends tu par "la compilation ne se réalise pas" ? Est-ce vraiment des erreurs de compilation ou des erreurs à l'édition des liens et lesquelles?

    Il ne faut pas confondre bibliothèque et fichier d'entête, même s'ils sont liés.
    Si le fichier d'entête B à besoin du fichier d'entête A (ici oui car ClasseB a une fonction qui retourne un ClasseA), alors forcément le fichier d'entête A doit être fourni.
    On peut tout à fait créer une bibliothèque B et une bibliothèque A. Et a priori la bibliothèque B ne sera pas suffisante pour l'utiliser dans une application, mais ça dépend du code dans B.

    Pour un {ClasseB.h , ClasseB.lib} autosuffisant, il faut inclure la ClasseA.lib dans la ClasseB.lib, mais le fichier ClasseA.h doit être aussi fourni (ou recopié dans ClasseB.h.)
    On peut "masquer" des objets internes à la condition qu'il ne soient pas visibles dans les fichiers d'entête nécessaires. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class ClasseA;  // il existe quelque part une ClasseA
    class ClasseB {
        public:
            ClasseB();
            ClasseA& test();  // la fonction test retourne une référence sur la ClasseA
        };
    int main() {
        ClasseA&  x = ClasseB{}.test();   // ok possible sans ClasseA.h tant qu'on ne cherche pas à utiliser x
        ClasseA    a = ClasseB{}.test();  // impossible d'avoir un objet ClasseA, on n'en connait pas les constituants.
    }

  3. #3
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut
    Super!

    Tu as répondu et même allé plus loin que ma question!

    Je comprends très bien pourquoi ça ne marche pas. J'avais un doute mais avec ta réponse et un peu de pragmatisme, je me rends compte que ce doute n'avait pas lieu d'être. Je me demandais si le fait d'inclure le header de A dans le .cpp de B ne pouvait pas régler le problème de "ce qu'est un objet A" par un mécanisme que je ne comprenais pas.

    Ca veut dire par exemple si je veux créer une bibliothèque avec une fonction qui retourne un std::vecteur, alors je suis normalement obligé d'inclure vector.h à mon projet (où alors il doit être installé chez le client).

    Du coup supposons que j'ai validé des tests chez moi avec ma version de MA stdlib, alors si mon client utilise la bibliothèque que je lui fournis (que j'ai programmé avec des retours sur référence comme toi ou pointeur) alors il risque d'avoir des tests qui ne passent pas (si des factorisations ont été mal faites : ok dans ce cas l'exemple est extrême mais c'est juste pour comprendre).

    Du coup bis dans mon cas, vu que la bibliothèque B est créer, je peux l'utiliser à condition d'inclure un lien vers un ClasseA.h dans mon projet? (dans ce cas évidemment il faudra que je m'assure que c'est le bon header avec le bon .lib).

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Généralement, on conçoit un header "chapeau" pour la librairie, qui n'inclura que les headers des classes accessibles aux utilisateurs de la librairie.

  5. #5
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut
    On peut "masquer" des objets internes à la condition qu'il ne soient pas visibles dans les fichiers d'entête nécessaires.
    Ok je comprends pourquoi dans le header où les objets ne sont pas définis on ne peut appeler ces objets.

    Ce que je ne comprends pas par contre c'est pourquoi le cas suivant ne fonctionne pas :

    Voici mon header dans les deux cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class QSerialPort;
     
    namespace QtClasseNameSpace {
        class QtClassLibrary1
        {
        public:
            QtClassLibrary1();
            inline int test(int a) { return a; };
        private:
            QSerialPort* mPort;
        };
    }

    Le QtClassLibrary1.cpp dans le premier cas. Lui fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include "QtClassLibrary1.h"
    #include "qserialport.h"
     
    namespace QtClasseNameSpace {
        QtClassLibrary1::QtClassLibrary1()
        {
            //mPort = new QSerialPort;
        }
    }
    Celui-ci ne fonctionne pas : perte des liens.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "QtClassLibrary1.h"
    #include "qserialport.h"
    namespace QtClasseNameSpace {
        QtClassLibrary1::QtClassLibrary1()
        {
            mPort = new QSerialPort;
        }
    }
    Est-ce qu'il y a une légère différence dans ce cas entre l'utilisation d'un pointeur ou d'une référence que je n'aurais pas vue?

    Moi ce que j'ai envie de lui dire au compilo c'est "hey frere : je vais fournir des .lib mais en revanche tu n'auras pas les .lib de qt. Il faut que le .lib que je fournisse suffise à mon client suffise parceque lui n'a pas qt". Je rame... je rame... Je ne sais même pas si c'est possible... Et si ce n'est pas possible ça voudrait dire que je dois filer toutes les dépendances QT (header + .lib) dans le dossier de QtClassLibrary1.lib? C'est un peu chiant non? Je'aimerais bien que la petite popote interne reste la petite popote interne.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Si ta question est : J'utilise Qt et je ne souhaite pas un installation sans Qt. La réponse est simple : c'est impossible. Les codes Qt sont dans les bibliothèques Qt et sont nécessaires.
    Si on prend tes exemples. Dans un cas tu indiques la présence d'un pointeur => aucun problème, aucun code spécifique n'est utilisé. Dans l'autre cas, tu utilises l'objet => le code Qt est nécessaire.

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Est-ce qu'il y a une légère différence dans ce cas entre l'utilisation d'un pointeur ou d'une référence que je n'aurais pas vue?
    Où vous voyez l'utilisation d'une référence dans votre code ???

    C'est toujours des pointeurs ( et nus en plus, c'est CACA, les pointeurs intelligents sont nos amis).

    Dans les 2 cas, vous déclarez de manière anticipés la classe "QSerialPort", juste pour que le compilateur vous foute la paix lors de la déclaration de votre champ "mPort".
    Cela fonction dans le premier cas parce que vous ne faite rien avec le type "QSerialPort", donc le compilateur n'a pas besoin de savoir autre chose que c'est un type connu et qui sera fourni à l'édition de lien.
    Mais dans le second cas, vous demandez au compilateur de générer un appel à l'un des constructeur de "QSerialPort", et là, le compilateur se doit de vérifier que ce constructeur (celui avec une signature compatible avec les paramètres que fourni le code d'appel) existe bien, ou que des règles de conversions implicites permettent d'en trouver au moins un.
    Comme vous êtes gentil avec le compilateur, vous faites un '#include "qserialport.h"' pour qu'il puisse vérifier tout ça, c'est la fonction même des .h.

    Mais c'est ballot, aucun des constructeurs définis dans ce .h ne correspond à la signature que votre code tente d'utiliser.
    https://doc.qt.io/qt-5/qserialport.html
    (Bon, ici, le premier constructeur devrait faire le job, mais on ne connait pas votre version de Qt ni le message d'erreur, donc je suppute)

    Il y a donc une très grosse différence entre déclarer une variable (où une déclaration anticipée du type peut suffire) et se servir de la variable/du type.

    Moi ce que j'ai envie de lui dire au compilo c'est "hey frere : je vais fournir des .lib mais en revanche tu n'auras pas les .lib de qt. Il faut que le .lib que je fournisse suffise à mon client suffise parceque lui n'a pas qt". Je rame... je rame... Je ne sais même pas si c'est possible...
    C'est tout à fait possible, il faut juste demander à ton linker d'incorporer le code des librairies que ta librairie utilise.
    C'est fonction de ton linker.
    Pour Visual Studio (mais il doit avoir moins bourrin):
    https://docs.microsoft.com/en-us/cpp...s?view=vs-2017

    J'arrive plus à trouver les options moins bourrins (je sais plus si c'est pas les réglages par défaut de la génération d'un .lib qui faut déjà tout le taf)

    Si vous voulez un contrôle absolu de la manipe :
    https://docs.microsoft.com/en-us/cpp...y?view=vs-2017

Discussions similaires

  1. Inclusion et utilisation d'une bibliothèque externe
    Par Eranos dans le forum Qt Creator
    Réponses: 1
    Dernier message: 12/02/2018, 10h45
  2. Réponses: 36
    Dernier message: 25/08/2014, 12h17
  3. Inclusion d'une bibliothèque
    Par khadijadadou dans le forum Débuter
    Réponses: 1
    Dernier message: 20/09/2013, 08h42
  4. Installation d'une bibliothèque
    Par Empty_body dans le forum JBuilder
    Réponses: 3
    Dernier message: 09/02/2006, 19h43
  5. Réponses: 19
    Dernier message: 26/04/2004, 08h54

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