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

Bibliothèques C++ Discussion :

[Bibliothèque] Gérer l'importation template


Sujet :

Bibliothèques C++

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 10
    Par défaut [Bibliothèque] Gérer l'importation template
    Bonjour à tous

    J'ai un petit soucis qui m'embête depuis plusieurs jours :

    Je crée une petite bibliothèque qui se présente actuellement sous la forme d'une bibliothèque dynamique (dll pour window).

    Donc, les classes et méthodes sont lus dans la bibliothèque, c'est dynamique, tout ça tout ça.
    Le petit problème, c'est que ma bibliothèque a une partie qui est devrait être en statique (template).

    Je vais faire un petit exemple :

    • Partie dynamique :
      • Classe A
      • Classe B
    • Partie statique
      • Classe C (template)


    Le problème, c'est que la classe C a pour attribute la classe A et la classe B.
    Donc, le compilo va construire une classe C dans le projet extérieur, et va devoir y intégrer une classe A et une classe B.

    Et là, malheur ! Classe A et Classe B sont dynamiques !
    Le compilateur est très fâché. On lui a dit que les classes A et B sont dans une bibliothèque dynamique et voilà qu'il doit les intégrer dans le projet de façon statique pour la classe template C !

    Et j'avoue que je ne vois pas du tout comment résoudre ça.
    En fait, la seule solution que je vois, c'est de compiler 2 fois les classes A et B. Une fois dans la bibliothèque dynamique et une fois dans la bibliothèque statique.

    Qui plus est, je dois mettre les classes A et B statiques dans un nouveau namespace pour éviter les ambiguïtés.

    Voici donc ma question : existe-t-il une méthode plus élégante à un tel problème ?

    Je vous remercie d'avance pour toute réponse
    Passez une agréable journée

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour et bienvenu sur le forum,
    Peux tu montrer comment tu définis tes classes A et B. Je soupçonne un mic-mac sur les __declspec(dllexport)/__declspec(dllimport) ?

    [EDIT]: je viens de faire un essai avec une DLL exportant une classe A, une classe B et intégrant une classe template ayant un membre A et B.
    Je crée une application qui utilises A, B, la classe template instanciée avec un int, la classe template instanciée avec un A, la classe template instanciée avec un B.... et tout fonctionne. D'où le renforcement de mes soupçons. Peux-tu montrer des exemples simplifiés de ton A, B et de ta classe template qui reproduisent ton problème. Il faudra certainement aussi que tu jettes un coup d'œil sur les directives de compilation de tes 2 projets.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 10
    Par défaut
    Merci pour la bienvenue et merci pour l'aide

    J'utilise Code::Blocks, donc pas de __declspec(dllexport)/__declspec(dllimport).

    J'avoue être assez frustré car je n'arrive pas à reproduire le bug en simplifié.

    Mais bon, la bibliothèque est imposante et il n'est pas évident de comprendre la source de ce warning.

    J'explique globalement, au cas où un détail explirerait le bug sans que je le sâche.

    La bibliothèque A utilise elle-même une autre bibliothèque B dynamique.

    Lorsque l'on crée une classe template, elle sert à du polymorphisme pour la bibliothèque A (il s'agit d'élements intégrés dans un graphe que l'on récupère pour les manipuler). Le graphe se trouve dans la bibliothèque A.
    Ces éléments manipulent des classes de la bibliothèque B.

    Lorsque l'élément intégré dans le graphe de la bibliothèque dynamique A est une classe template, il y a warning d'auto-importation.
    Sinon, aucun problème.

    Ce que je vais faire, en attendant de mieux comprendre pour pouvoir simplifier la chose.

    Si quelqu'un est courageux, le temps que je comprenne mieux la source du problème pour l'arranger, il peut reproduire le bug.

    Le code est simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <Interface.hpp>
     
    struct Element
    {
        int variable;
    };
     
    int main()
    {
        Interface _Interface;
        gui::Button Button = _Interface.Add<gui::Button>(); // Ok
        gui::List List = _Interface.Add<gui::List<Element> >(); // Warning
    }
    Je comprendrais que vous ne vous donniez pas la peine, c'est à moi de le faire après tout Mais je suis un peu dépassé et donc je risque de mettre un peu de temps à trouver l'erreur simplifiée. Si vous soupsonnez l'origine bug, je vous invite à essayer, sinon ne vous donnez pas ce mal

    Merci beaucoup quoiqu'il en soit ne serait-ce que pour votre patience.
    Bonne soirée à tous

    edit : Je pense pas que le problème soit un problème de conception mais bien de paramètres de compilation. Le problème, c'est que je ne m'y connais pas du tout de ce côté là. La seule chose que je comprends, c'est que je dois autoriser l'auto-importation. Et que --enable-auto-import ne fonctionne pas

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    J'ai refais le même essai avec Code::Block et gcc qu'hier, et.... pas de problème !
    Je penses comme toi qu'il doit y avoir un détail dans les options de compilation.
    Peux-tu les préciser (pour la DLL et pour l'appli)?

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut, et bienvenue sur le forum.

    Même si tu travaille avec Code::Blocks, et quel que soit le compilateur utilisé, si tu veux créer une dll, tu dois prévoir quelque chose ressemblant à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #if defined(BUILDLIB)
        #define EXPORTMYLIB __declspec(dllexport)
    #else
        #define EXPORTMYLIB __declspec(dllimport)
    #endif
    et définir les fonctions exportées par la dll sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    EXPORTMYLIB void foo(/*paramètres éventuels */)
    {
        /*...*/
    }
    Le but est que, lorsque tu compilera ta dll (il faudra avoir ajouté un -dBUILDLIB dans les options de compilation de la dll), le code soit remplacé par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    __declspec(dllexport) void foo(/*paramètres éventuels */)
    {
        /*...*/
    }
    et que, lorsque tu compilera un programme utilisant cette dll (où -dBUILDLIB n'est pas ajouté dans les options de compilations du projet), le code soit remplacé par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    __declspec(dllimport) void foo(/*paramètres éventuels */)
    {
        /*...*/
    }
    Au final, lorsque tu compilera la dll, le code préviendra que la fonction est exportée, et, lorsque tu compilera ton application, le code préviendra que la fonction... se trouve dans la dll

    NOTA: n'hésite pas à personnaliser BUILDLIB et EXPORTMYLIB de telle manière à ce que chaque dll ait ses propres termes
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut, et bienvenue sur le forum.

    Même si tu travaille avec Code::Blocks, et quel que soit le compilateur utilisé, si tu veux créer une dll, tu dois prévoir quelque chose ressemblant à
    gcc m'exporte par défaut tous les symboles du projet DLL sans avoir à les préfixer par quoique ce soit et sait ensuite les importer sans problème. (Je n'ai pas fait le test, mais j'imagine que si je fait des variables globales/fonctions libres statiques, il ne va pas les exporter.)

    [EDIT] Exemples de fichier (côté DLL):
    a.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #ifndef A_H
    #define A_H
     
     
    class A
    {
    public:
       A(void);
       ~A(void);
    };
     
    #endif
    a.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include "A.h"
    #include <iostream>
     
    A::A(void)
    {
       std::cout<<"coucou d'un A"<<std::endl;
    }
     
    A::~A(void)
    {
       std::cout<<"byebye d'un A"<<std::endl;
    }
    Coté application :
    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "A.h"
     
    int main()
    {
       A a;
    	return 0;
    }

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 10
    Par défaut
    Exact, Code::Blocks rejette tout __declspec(dllexport)/__declspec(dllimport) lors de la compilation ou de l'utilisation de la bibliothèque.

    Petite note que j'ai oublié : la bibliothèque utilise deux variables statiques. La classe template et ses attributs les utilisent. C'est le plus gros soupson que j'ai d'un point de vu de conception.
    Mais je n'ai rien réussi à reproduire en simplifié avec des variables statics qui donne le warning. Ce qui me laisse perplexe

    Pour la compilation de la bibliothèque :

    create import library - ok
    create .DEF exports file - ok

    A part ça, il n'y a que les options pas défaut

    Je n'ai pas le temps de m'y appliquer aujourd'hui, mais demain je reproduirais point par point la bibliothèque en simplifié jusqu'à optenir le warning.
    A partir de là, ça sera plus facile pour vous de m'expliquer l'origine du problème

    Je vous remercie beaucoup pour votre aide, encore une fois bonne journée à tous

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Le problème, c'est que le propre d'une dll est d'être fournie pour tous les compilateurs...

    cela implique que tu doit fournir un fichier d'en-tête capable de s'adapter à ceux qui ont éventuellement besoin d'un __declspec(dllimport)

    De plus, même s'il ne prend pas en compte les instructions concernant les non exportations, C::B (et Gcc) fonctionnent très bien avec l'utilisation des __declspec:

    Crée un projet (dynamic link library), et tu remarquera qu'il te crée un fichier main.h qui contiendra, justement, les lignes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #ifdef BUILD_DLL
        #define DLL_EXPORT __declspec(dllexport)
    #else
        #define DLL_EXPORT __declspec(dllimport)
    #endif
    d'un autre coté, si tu crée un autre projet (shared library), tu crées un fichier nommé (arbitrairement) buildlib.hpp et qui contient le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef BUILDLIB_HPP_INCLUDED
    #define BUILDLIB_HPP_INCLUDED
    #if defined(BUILD_LIB)
        #define MYDLLEXPORT __declspec(dllexport)
    #else
        #define MYDLLEXPORT __declspec(dllimport)
    #endif
    #endif // BUILDLIB_HPP_INCLUDED
    que, dans les options du projet (project->build options ->onglet "compiler setting", sous onglet "defines"), tu défini BUILD_LIB tel quel (en écrivant simplement "BUILD_LIB" sans les guillemets) et qu'enfin, tu crées une classe sous la forme de
    (MyClass.hpp)
    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
     
    #ifndef MYCLASS_H
    #define MYCLASS_H
    // je n'arrive pas à indiquer à C::B que le fichier
    // dois d'office être inclu :P
    #include <buildlib.hpp> 
    class MYDLLEXPORT MyClass
    {
        public:
            MyClass();
            ~MyClass();
            void foo();
        protected:
        private:
    };
    void foo();
    #endif // MYCLASS_H
    (fichier MyClass.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
    #include "MyClass.hpp"
    #include <iostream>
    /*MYDLLEXPORT*/ MyClass::MyClass()
    {
        //ctor
    }
     
    /*MYDLLEXPORT*/ MyClass::~MyClass()
    {
        //dtor
    }
    /*MYDLLEXPORT */ void MyClass::foo()
    {
        std::cout<<"MyClass:: foo()";
    }
    void foo()
    {
        std::cout<<"unexported foo()";
    }
    tant le compilateur que C::B s'adaptent très bien aux __declpsec

    Il n'y a pas non plus de problème si tu ne veux exporter qu'une fonction de classe, sous une forme proche de
    (fichier Second.hpp)
    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
     
    #ifndef SECOND_HPP
    #define SECOND_HPP
    #include <buildlib.hpp>
     
     
    class Second
    {
        public:
            Second();
            virtual ~Second();
            static MYDLLEXPORT void foo(); //sinon cela n'a aucun sens
        protected:
        private:
    };
     
    #endif // SECOND_HPP
    (fichier Second.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
    #include "Second.hpp"
     
    #include <iostream>
    Second::Second()
    {
        //ctor
    }
     
    Second::~Second()
    {
        //dtor
    }
    MYDLLEXPORT void Second::foo()
    {
        std::cout<<"Second::foo()"<<std::endl;
    }
    et tu obtiens bel et bien uniquement les informations déclarées exportables dans le fichier def:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    EXPORTS
        _ZN6Second3fooEv @1
        _ZN7MyClass3fooEv @2
        _ZN7MyClassC1Ev @3
        _ZN7MyClassC2Ev @4
        _ZN7MyClassD1Ev @5
        _ZN7MyClassD2Ev @6
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 10
    Par défaut
    Etrange, moi il me les a rejété (j'avais exactement comme ci-dessous).

    J'ai dût faire une bourde quelque part

    Je pense avoir comprit pourquoi. J'avais déclaré GUI-SFML pour ma macro. Et le '-' est pas bien vu.

    J'avais pas fait attention

    Je vais tester tout ça et je vous tiens au courant

    edit : haha, ça marche ! Je n'ai plus de warning

    je vous remercie infiniment pour votre aide Je viens d'apprendre plusieurs choses bien intéressantes (et indispensable finalement) au passage.

    Je vous souhaite à tous une agréable journée

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

Discussions similaires

  1. [AC-2010] Importer Template Excel Vers Access
    Par sschoonjans dans le forum IHM
    Réponses: 5
    Dernier message: 25/03/2013, 11h47
  2. Export / Import template
    Par bugz57 dans le forum NetBeans
    Réponses: 0
    Dernier message: 22/07/2010, 11h48
  3. Peut on gérer les imports ?
    Par troxsa dans le forum VB.NET
    Réponses: 1
    Dernier message: 07/01/2009, 17h06
  4. Gérer l'import/Export de données entre 2 base ACCESS
    Par DanaX dans le forum VBA Access
    Réponses: 2
    Dernier message: 15/11/2007, 15h18
  5. Réponses: 2
    Dernier message: 07/07/2007, 14h24

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