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 :

Création de bibliothèque


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut Création de bibliothèque
    Bonjour,

    Je cherche à créer une bibliothèque C++ (statique ou dynamique, je n'ai pas décidé) qui encapsule l'API sockets de la plateforme. C'est à dire WinSock pour windows, posix sockets pour linux.

    Je commence par windows, et je dois donc utiliser la bibliothèque WS2_32.lib (qui utilise elle même une dll je crois). Mais voilà, j'aimerais qu'un utilisateur de ma bibliothèque n'ait à se linker qu'avec la mienne !

    Comment procéder dans les 2 cas (statique et dynamique), et est-ce possible ?

    Note : Jusque là j'arrive à créer une bibliothèque statique, mais tout exécutable qui l'utilise doit aussi se linker à WS2_32.lib (et après ma bibliothèque).

    Note 2 : Pas trop envie d'utiliser des astuces du genre #pragma comment(lib, "WS2_32.lib") dans le code des headers, car trop spécifique au compilateur VC++.

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Si tu crées une bibliothèque dynamique tu n'auras aucun problème.

    Pour une bibliothèque statique, là ça dépend fortement de ton environnement de développement.

    Avec Visual C++, il suffit d'ajouter ws2_32.lib dans les "input libraries" et il sera lié automatiquement dans tout programme utilisant ta bibliothèque.

    Avec gcc et ses dérivés c'est déjà plus embêtant, il faut faire tourner une commande externe qui extrait les .o de libws2_32 et les ajoute à ta bibliothèque (un bibliothèque .a n'est qu'une bête archive de fichiers .o). Sous Windows cela signifie qu'il te faut un environnement Linux (msys, cygwin).
    Je détaille cette manipulation à la fin de ce tutoriel :
    http://www.sfml-dev.org/tutorials/1.3/start-cb-fr.php

  3. #3
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    A moins bien sûr que ça soit à but pédagogique, ça n'a pas tellement d'intérêt de refaire ce qui existe déjà, je pense notamment à Boost.Asio.

    Sinon une petite mise en garde sur l'inclusion de bibliothèque statique à l'intérieur d'une autre : c'est très dangereux !
    Avec ar notamment, deux fichiers .o qui portent le même nom vont entrer en concurrence et l'un va écraser l'autre, et ce presque silencieusement...
    Et puis si l'utilisateur final veut aussi par ailleurs lier avec une bibliothèque sournoisement déjà incluse dans une autre mais pas avec la même version exactement, ça va lui poser problème sachant qu'en général c'est encore une fois effectué silencieusement.

    MAT.

  4. #4
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Merci de vos réponse, c'est très intéressant. la meilleure solution serait donc de créer une bibliothèque dynamique a priori...

    Je n'ai aucune expérience en la matière, j'ai regardé quelques cours, mais je ne vois pas encore comment gérer la dépendance à une bibliothèque statique pour une dll !

    Disons que je crée ma libSockets.dll, mais qu'elle dépend de WS2_32.lib. Comment je répercute ça dans le code/ou plutôt les options de compilation ? J'ai juste besoin de compiler en liant à la bibliothèque statique ? L'utilisateur n'aura vraiment besoin de rien ajouter d'autre que ma bibliothèque ?

    Pour l'aspect refaire ce qui existe déjà, je connais boost.asio qui est très performant mais c'est effectivement dans un objectif pédagogique que j'essaie de reproduire ce modèle avec des bibliothèques compilées. Parce que justement je maîtrise beaucoup mieux la programmation C/C++ que la compilation C/C++...

    Edit: Autre question : la manipulation d'intégration d'une bibliothèque externe dans une autre est effectuable avec cygwin ou msys. Mais est-elle faisable pour des bibliothèques Windows à partir de linux ? En d'autre termes, les archives générées par ar sous linux sont-elles utilisables sous Windows si le code est compilé pour Windows ? Ça m'éviterait d'installer cygwin ou msys étant donné que j'ai un dual boot linux/windows.

  5. #5
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Autres questions :

    Le préfixe __declspec (dllexport) est-il réellement important dans les sources et headers du projet dll ?
    Le préfixe __declspec (dllimport) est-il réellement important dans les headers du projet utilisant la dll ?
    Ces préfixes doivent être utilisés dans quels cas (fonctions ? classes ?) ?

    Après quelques tests ça a l'air de fonctionner sans le préfixe, je me demande à quoi il sert donc...

  6. #6
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Oui ils sont important : cela permet au compilateur (VC en l'occurence) de savoir quels symboles de la dll sont à exporter, et quels symboles utilisés par l'application qui utilise la dll sont à importer.

    Donc, tu dois faire en sorte que dans tes headers les fonctions et méthodes qui sont dans définis dans ta dll mais dont l'application cliente n'aura que la déclaration soient indiqués comme __declspec (dllexport) pour le code source de la dll, et __declspec (dllimport) pour le code source de l'application client.

    Tu dois l'indiquer pour les fonctions et méthodes, mais tu peux aussi indiquer que les méthodes de toute une classe sont dllexport/dllimport, en mettant ce mot après class dans la déclaration de ta classe.

    Habituellement on utilise des macros qui déclarent l'un ou l'autre selon quel code source va être compilé.


    Par contre si ton code est totalement contenu dans un header (par exemple si c'est une lib totalement templatée) alors tu ne dois pas les utiliser puisque le code sera généré à la compilation de l'application cliente et non dans la dll (sauf si elle en utilise mais ce sera local a la dll).

    Attention toutefois, ce specifier n'est valide qu'avec VC (donc sous windows). Il me semble que gcc exporte tous les symboles par défaut, il faut donc faire la démarche inverse et spécifier ce qui ne devrait pas être exposé publiquement (principalement pour gagner en perfs à la compilation). Et de toutes façons le specifier est différent.

  7. #7
    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
    En général:

    Le projet de librairie inclus un header de précompilation:
    precompiled.h
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #ifndef MALIB_STATIC
    #define MALIB_API  __declspec(dllexport)
    #endif
     
    #ifdef WIN32
    #include <windows.h>
    #include <winsock2.h>
    #endif
    ...

    Puis un header pour les defines de la "libraire"
    malib.h
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #ifndef MALIB_API
    #ifdef MALIB_STATIC
    #define MALIB_API
    #else
    #define MALIB_API   __declspec(dllimport)
    #endif
    #endif

    Puis enfin... les headers des trucs à exporter:
    monobjet.h
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include "malib.h"
     
    class MALIB_API MonObjet
    {
       ...
    };

    monobjet.cpp
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include "precompiled.h"
    #include "monobject.h"
     
    MonObjet::xxxxx
    ...

    Comme ça... plus de problême.... et tu peux avoir une version statique et une version DLL par simple option de compilation

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Le dllexport est important, mais le dllimport ne l'est pas. Il permet toutefois une optimisation.
    Calling an imported function, the naive way
    How a less naive compiler calls an imported function
    What happens when you get dllimport wrong?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Parfait parfait !

    Ca répond à presque toutes mes interrogations. Un ou deux détails cependant :

    - Je lis des informations contradictoires sur le net à propos de MinGW, certains sujets disent qu'il faudrait utiliser les préfixes d'import et d'export et d'autres non. Mais pour moi ça fonctionne sans (tout doit être exporté par défaut). Alors comment procéder avec ce compilateur ?

    - Si GCC met par défaut les méthodes en visibilité publique (exportées en dll), comment les masquer ?

    - Comment masquer une méthode particulière d'une classe exportée entièrement avec la méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class MALIB_API MaClasse
    {
    ...
    }

  10. #10
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    A priori, suivre le Pimpl idiom est le seul moyen de cacher une partie de l'interface.

    Sinon pour gcc, si tu lis l'anglais tu as toutes les explications là : http://gcc.gnu.org/wiki/Visibility

  11. #11
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Pas de soucis pour l'anglais^^

    Pour GCC j'étais tombé sur cet article. Mais en fait j'aimerais surtout savoir quel préfixe utiliser pour MinGW ! Parce qu'en théorie, MinGW, c'est GCC... mais je vois partout utiliser le __declspec(dllexport) avec lui, et pas __attribute__ ((visibility("default"))).

    Et le Pimpl idiom, si je comprends bien, c'est plutôt utile pour masquer la structure des attributs. Mais si j'ai une classe avec 70 méthodes, et que je veux que seulement 3 d'entre elles soient masquées (j'entends par la non-exportées), avec VC je procède comment ? Je pensais qu'il était possible de mettre la classe en export (class MALIB_API MaClasse) et de rajouter un préfixe de masquage sur les 3 méthodes concernées, du genre le __attribute__ ((visibility("hidden"))) de GCC.

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Déjà, pourquoi ne pas les déclarer private ?
    Même si elles sont exportées, elles seront inutilisables pour le code utilisant la DLL...

    Je rappelle à ce sujet qu'une classe exportée dans une DLL par un compilateur n'est utilisable que depuis du code fait par le même compilateur...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    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
    Citation Envoyé par Médinoc Voir le message
    Déjà, pourquoi ne pas les déclarer private ?
    Parcequ'il suffit de modifier le header pour retrouver l'accès à la fonction ?

  14. #14
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Je rappelle à ce sujet qu'une classe exportée dans une DLL par un compilateur n'est utilisable que depuis du code fait par le même compilateur...
    Ah ?
    Déjà, pourquoi ne pas les déclarer private ?
    Même si elles sont exportées, elles seront inutilisables pour le code utilisant la DLL...
    Mais j'essaie d'optimiser le code en fait. Si c'était aussi simple que de les déclarer en private, pourquoi se serait-on embêté à créer ces préfixe de visibilité ? Il est aussi question de symboles exportés, qui font grossir la taille des dll, et augmentent les risques de confusion.

    J'ai aussi noté un exemple du lien de Klaim :
    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
    #ifdef _MSC_VER
      #ifdef BUILDING_DLL
        #define DLLEXPORT __declspec(dllexport)
      #else
        #define DLLEXPORT __declspec(dllimport)
      #endif
      #define DLLLOCAL
    #else
      #ifdef HAVE_GCCVISIBILITYPATCH
        #define DLLEXPORT __attribute__ ((visibility("default")))
        #define DLLLOCAL __attribute__ ((visibility("hidden")))
      #else
        #define DLLEXPORT
        #define DLLLOCAL
      #endif
    #endif
     
    class DLLEXPORT SomeClass
    {
       int c;
       DLLLOCAL void privateMethod();  // Only for use within this DSO
    public:
       Person(int _c) : c(_c) { }
       static void foo(int a);
    };
    Dans ce code, si le compilateur est GCC, pas de soucis, privateMethod() n'est pas exportée. Maintenant si le compilateur est VC, on se retrouve avec le code suivant après expansion des macros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class __declspec(dllexport) SomeClass
    {
       int c;
       void privateMethod();  // Only for use within this DSO
    public:
       Person(int _c) : c(_c) { }
       static void foo(int a);
    };
    Et là privateMethod() est exportée ! Y a pas une erreur (à moins que VC n'exporte pas les données private) ? Un autre moyen de masquer privateMethod() comme je demandais aux posts précédents ?

    J'ai encore poussé mes tests :
    J'ai essayé la technique class __declspec(dllexport) MaClasse, au lieu de mettre le préfixe devant chacune des méthodes, mais j'ai plusieurs Warnings à la compilation du genre :
    SocketException.hpp|12|warning C4275: non dll-interface class 'std::exception' used as base for dll-interface class 'SocketException'|
    Parce que la classe std::exception n'est pas déclarée exportée et que ma classe en hérite, ou encore :
    SocketException.hpp|23|warning C4251: 'SocketException::m_description' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'SocketException'|
    (lien intéressant)
    Parce que l'attribut (qui est protected) est un std::string et que std::string n'est pas une classe exportable ! VC essaie d'exporter les attributs de ma classe ? Pourquoi MinGW ne se plaint pas ?

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Dans ce cas, la méthode COM: On n'exporte pas la classe, on expose juste une "interface" (classe abstraite dont toutes les fonctions sont virtuelles) et on exporte juste une fonction qui retourne un pointeur vers une instance de classe.

    L'overhead dû aux appels virtuels est le même que celui dû aux appels de DLL de toute façon, donc pas de soucis au niveau performance.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Bon j'ai moi-même effectué divers tests pour comparer MinGW et VC++ au sujet des exports de fonctions dans les dll :

    specifier devant nom de classe :
    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
    class MYDLL_API MyDLL
    {
    public:
        void publicFunc();
        inline void inlineFunc()
        {
            std::cout << "inlineFunc1" << std::endl;
        }
        std::string m_string;
     
     
    protected:
        void protectedFunc();
     
     
    private:
        void privateFunc();
    };
    Specifier devant méthode :
    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
    class MyDLL
    {
    public:
        MYDLL_API void publicFunc();
        inline void inlineFunc()
        {
            std::cout << "inlineFunc1" << std::endl;
        }
        std::string m_string;
     
     
    protected:
        MYDLL_API void protectedFunc();
     
     
    private:
        void privateFunc();
    };
    VC++ :
    - Par défaut n'exporte rien
    - Le specifier __declspec(dllexport) devant le nom de classe force l'export de toutes les méthodes (public, protected, private, inline) et des attributs également
    - Le specifier devant une méthode force l'export de la méthode (logique)


    MinGW :
    - Par défaut exporte toutes les méthodes(mais uniquement les non-inline) : public, protected et private
    - Le specifier __declspec(dllexport) devant le nom de classe équivaut au comportement par défaut (pas tout-à-fait, l'entrée en gras est alors supprimée du fichier .DEF : )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    EXPORTS
        _ZN5MyDLL10publicFuncEv @1
        _ZN5MyDLL11privateFuncEv @2
        _ZN5MyDLL13protectedFuncEv @3
        _get_output_format @4
    - Le specifier devant les méthodes à la place du nom de la classe supprime le comportement par défaut et n'exporte que les méthodes spécifiées exportables
    - Une méthode inline n'est pas exportable/importable (l'export est ignoré et l'import échoue)
    - Les attributs ne sont pas exportés mais accessibles quand-même (aucune trace de l'attribut m_string dans le fichier .DEF généré par code::blocks et pourtant j'ai accès à cet attribut (public pour le test))


    Pour les deux :
    - Le specifier __declspec(dllexport) est inutile sur les définitions des fonctions, il ne sert que sur le prototype (dans le header) (aucun changement de taille de dll ou d'exécutable, aucun symbole non trouvé avec ou sans specifier dans le .cpp).


    J'ai réalisé les tests avec code::blocks. Le test de la méthode inline pour VC++ est réalisé comme suit :
    - Génération de la DLL avec export de inlineFunc() qui affiche "inlineFunc1"
    - Modification du header pour que inlineFunc affiche "inlineFunc2"
    - Génération du client de la DLL, qui appel juste inlineFunc()

    Le résultat est "inlineFunc1", ce qui veut dire que le client n'a pas inliné la fonction mais est bien allé la chercher dans la dll ! C'est impossible avec MinGW qui refuse d'exporter et donc d'importer la fonction inline. Mais en même temps c'est plus logique...


    J'espère que ça en aidera certains, pour ma part j'abandonne l'idée d'exporter la classe entière (trop de problèmes avec VC++, pas de masquage possible avec les deux compilateurs), j'exporterai seulement les méthodes utiles.

    Edit : un test de plus, les méthodes virtuelles :
    - On est obligé d'exporter une méthode virtuelle (non pure) si on veut l'utiliser dans l'application cliente (logique)
    - Incompréhension : sous MinGW, on est obligé d'exporter un constructeur dès lors qu'on exporte une méthode virtuelle (ou alors je fais mal quelque chose mais je ne vois pas quoi vu la simplicité du code), sinon une erreur au linkage de l'exécutable apparait :
    undefined reference to vtable for MyDLL
    - Sous VC++, pas de soucis

  17. #17
    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
    Hmmm... je dirai que MinGW se plante...
    Pour une raison simple...

    Prenons la version 1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Toto
    {
         int   uneRef;
     
         inline int GetValue() { return uneRef; }
    };
    Prenons la version 2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Toto
    {
         int    uneRef;
         int    uneDeuxiemeRef;
     
         inline  int GetValue() { return uneDeuxiemeRef; }
    };
    J'ai un peu peur du résultat si un programme est compilé avec la version 2 et que la DLL est de version 1 ! Aucune erreur au link (il n'y a pas de fonction exportée), rien.... mais un crash certain à l'execution !

  18. #18
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 67
    Par défaut
    Mais quelle idée aussi de modifier les headers sans recompiler la dll ?

    Enfin là dans ton exemple ça risque de ne rien faire d'étrange (à part le fait que les valeurs ne sont pas initialisées). J'ai même testé et affecté une valeur à ta 2ème référence dans la fonction inline, et rien, pas de crash, la valeur est bien écrite, et la classe fait bien 2 * sizeof (int) (mémoire bien allouée pour le 2ème attribut). Maintenant si le constructeur est exporté, c'est le constructeur qui va faire crasher l'appli et pas la méthode inline.

    Un problème se posera en fait pour les méthodes exportées qui se servent des attributs de la classe. Mais rien à voir avec les fonctions inline, et rien de spécifique à MinGW.

    L'approche de VC supprime l'utilité du mot clé inline pour le client, puisqu'il permet d'importer la fonction depuis la dll au lieu de recopier le code. C'est une autre façon de voir les choses.
    Mais au final je pense que les méthodes inline ne sont pas faites pour les dll, qui permettent entre autres de ne pas exposer le code au client.

Discussions similaires

  1. Création de bibliothèques VBA
    Par Laestic dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 24/06/2008, 14h59
  2. Création de bibliothèque
    Par Le Furet dans le forum Général Conception Web
    Réponses: 5
    Dernier message: 07/06/2007, 16h49
  3. C++ et création de bibliothèque
    Par damien77 dans le forum C++
    Réponses: 2
    Dernier message: 26/03/2007, 10h56
  4. Problème : création de bibliothèque et utilisation
    Par damien77 dans le forum Code::Blocks
    Réponses: 8
    Dernier message: 21/03/2007, 23h56
  5. Pb création diagramme : bibliothèque non inscrite
    Par jeff37 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 12/08/2004, 17h38

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