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 :

Passage de librairies statiques en DLL


Sujet :

C++

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut Passage de librairies statiques en DLL
    Bonsoir à tous,


    J'ai deux librairies statiques. La première manipule des données sous forme de "T" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class CData<T>
    {
     
    };
     
    class CDataConnector<T>
    {
     
    };
     
    class CGesData<T>
    {
     
    };
    etc...

    La seconde définit les classes métiers, c'est à dire les "T" :
    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
    class CUser : public CData<T>
    {
    public:
       std::string& GetName();
       int GetAge();
     
    private:
       std::string m_strName;
       int m_iAge;
       // etc///
    };
     
    class CCar
    {
     
    };
    etc...

    J'aimerai passer la seconde librairie (la librairie métier qui s'appuie sur la librairie de gestion) en DLL, mais, comme j'ai peu d'expérience dans les DLL, je fais appel à vous.

    Après avoir définit et implémenté toutes mes classes métiers, que dois-je exposer ? J'imagine que c'est pas le "CUser.h" (qui inclue le CData.h qui lui inclu le CGesData etc...), le "CCar.h", si ?

    Vous pouvez me guider ?


    Merci à vous,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    J'aurais tendance à répondre : que veux-tu exposer ? Cela te donne ton interface à mettre dans ton .h et ton CUser en dérive ou utilise le pimpl idiom.

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Merci pour cette réponse rapide.

    Je veux exposer le CUser, CCar etc.. mais j'ai un point d'entrée qui est basée sur une hiérarchie éparpillée, qui fait dériger une classe concrête de tous les CGesData<T> :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class CGesManager : public CScatteredHierarchie<ListDeTypes, CGesData>
    pour résulter à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class CGesManager : public CGesData<CUser>, public CGesData<CCar>
    Ce "CGesManager" est une classe non template mais qui n'encapsule que des méthodes template, pour savoir à quel "Ges parent" se référer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template<class T> CGesManager::GetCount()
    {
        return CGesData<T>::GetCount();
    }
    Donc il faut que j'expose le CGesManager mais donc aussi le CGesData ? Tout comme le CUser viendra avec le CData ?

    L'objectif est que le programme utilisateur n'ai rien à compiler (car actuellement en librairie statique, c'est assez long compte tenu du nombre de classes à générer).


    Merci
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    C'est un peu tard et je ne comprend pas tous. MAis le pimpl idiom ne peut-il te servir pour séparer l'interface exposé des détails d'implémentation que n'ont pas à connaître les clients ?

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Bé je regarde ce "pimpl idiom" car je ne connais pas.

    Là j'ai passé le projet en DLL, ce que le programme utilisateur me mettait comme erreur de link, j'ai fait des "__declspec(dllexport)" devant puis c'est passé, mais la lenteur de compilation des classes du projet utilisateur me laisse penser que j'ai tout faux
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Ok, j'ai compris le pimpl ideom.

    En gros, mes classes CUser, CCar deviennent CUser_impl, CCar_implt (donc toujours avec leurs variables membres et leurs fonctions)

    Puis je fait une class CUser qui contient un pointeur vers CUser_implt en pré-déclarant cette classe CUser_implt et ainsi, le CUser.h ne contient que les méthodes, ainsi qu'une prédéclaration d'une classe.

    Dans le CPP de CUser, les méthodes (GetName, GetAge etc..) s'en réfèrent à CUser_implt::GetName et CUser_implt.GetAge

    Ainsi, pour le programme utilisateur, il ne lui reste juste l'entête des méthodes de CUser (sans inclusion de classe de base, ni membres internes) et l'implémentation (CUser_impl qui inclu les fichier de classes de base) étant "cachée", la compilation est donc plus rapide.

    Très astucieux, j'essaye ça dès que possible.

    Merci beaucoup
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  7. #7
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Ca se justifie si les utilisateurs n'ont à connaître que CUser et doivent ignorer CData<T>.
    En fait, tu as deux solutions :
    1 - héritage :
    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
     
    // classe exportée :
    class IUser
    {
    public:
         static smart_ptr<IUser> Creer();// retourne un CUser concret
         virtual void Methode1()=0;
         virtual void Methode2()=0;
     
         virtual ~IUser()=0;
    };
    // classe interne non exportée
    class CUser : public IUser , public CData<T>
    {
         virtual void Methode1();
         virtual void Methode2();
     
         virtual ~CUser();
    };
    ou
    2 - pimpl idiom
    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
     
    class CUser;
    // classe exportée
    class IUser
    {
    public:
         void Methode1();// appelle p_userImpl->Methode1();
         void Methode2();// appelle p_userImpl->Methode2();
    private:
        smart_ptr<CUser> p_userImpl;
    };
    // classe interne non exportée
    class CUser : public CData<T>
    {
         void Methode1();
         void Methode2();
    };
    Pour les DLL, personnellement, je préfère la second solution - le pimpl idiom. Mais c'est un simple gout personnel et peut être pas toujours approprié.

    Enfin, tout ça pour dire que ma question première : "que veux-tu exposer ?" doit se comprendre non seulement par ce que la classe déclare (membres) mais aussi par son héritage. Si tu ne veux pas exposer les classes parents alors il faut que tu dissocies soit avec un héritage d'une interface exposée soit avec un pimpl idiom. Dans ton cas, si CUser n'a pas à exposer CData<T> alors il ne doit pas apparaître dans ce qui fait parti de l'interface de ta DLL mais doit rester dans le code d'implémentation.

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Bé c'est parfait, j'ai tout ce qu'il me faut pour avancer. Je connaissais pas ces techniques


    Merci beaucoup
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut Avancement
    Bonjour,


    J'ai avancé sur ce passage en DLL, et voici ce que j'ai fait :

    Après une tentative avec le pimpl ideom, j'ai eu quelques soucis donc je suis passé par l'héritage :

    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
    class CUserImpl;
    class CUser
    {
    public:
       typedef CUserImpl TImpl;
     
       void GetIdent() = 0;
       void GetName() = 0;
    };
     
    class CUserImpl : public CUser, CData<CUserImpl>
    {
    public:
       // redéfinition des accesseurs
     
    private:
       TULongProperty m_ulIdent;
       TStringProperty m_strName;
    };
    Puis, dans ma hiérarchie éparpillée, il faut donc que je donne les classes *Impl :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // BusinessImpl.h
    #include "CUserImpl.h"
     
    typedef TTYPELIST_1(CUserImpl) TGesList;
     
    #include <kinGesDatas/CGesManager.h>
    // GesManager attend le TGesList pour hénérer la hiérarchie
    Là où ça se complique, c'est que je souhaite que l'utilisateur manipule des CUser et non des CUserImpl, sinon ça n'aura servit à rien.

    Donc je voulais proposer des fonctions templates, globales à mon espace de nom, par exemple celle pour récupérer un utilisateur via un index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Business.h
    template<class T> getAt(unsigned long ulIndex);
     
    // Business.cpp
    template<class T> getAt(unsigned long ulIndex)
    {
       return CGesManager::GetInstance().GetAt<T::TImpl>(ulIndex);
    }
    Sauf que bien évidemment j'ai des erreurs de link puisque cette fonction template n'est pas compilée dans la DLL.


    Que puis-je faire ?

    Merci beaucoup,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  10. #10
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Ben, dans ton cas, j'ai quand même l'impression qu'il faut se servir de l'héritage jusqu'au bout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    CUser const & getAt(unsigned long ulIndex)
    {
       return CGesManager::GetInstance().GetAt<T::TImpl>(ulIndex);
    }
    Bien sûr, tu renvois une référence donc l'objet doit avoir la bonne durée de vie.

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

Discussions similaires

  1. linker dll et librairie statique
    Par L4BiN dans le forum Bibliothèques, systèmes et outils
    Réponses: 3
    Dernier message: 19/10/2010, 20h48
  2. Librairie statique C et passage d'arguments
    Par guepe dans le forum MATLAB
    Réponses: 1
    Dernier message: 08/11/2007, 08h08
  3. Réponses: 2
    Dernier message: 19/08/2005, 17h02
  4. Membre statique et DLL
    Par Invité(e) dans le forum Windows
    Réponses: 2
    Dernier message: 15/04/2005, 15h04
  5. librairie statique/dynamique
    Par trop_wizz dans le forum MFC
    Réponses: 4
    Dernier message: 11/04/2005, 11h04

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