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 :

[C++ / DLL] Quelques questions concernant les templates


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Par défaut [C++ / DLL] Quelques questions concernant les templates
    Bonjour à tous,

    J'ouvre ce topic pour vous demander quelques précisions concernant l'utilisation de template en c++ avec des librairies dynamiques (dll). J'ai rencontré différents problèmes et je en sais pas si c'est un souci de configuration, de méconnaissance sur le language ou une limite technique (je suis novice en c++ ).

    J'ai comme projet de faire un petit moteur de jeu c++. Celui-ci ce défini par une dll qui contient les classes de mon moteur (gestionnaire de ressource, gestionnaire d'événements, classe de base de sprite...) et j'ai un petit executable qui va utiliser et enrichir les bases du moteur pour ses besoin (spécialisation de sprite, regles pour le jeu etc...).

    1) Premier cas : J'ai tenté de faire un service locator avec un template de façon à accèder à mes services comme j'ai l'habitude de le faire (je viens du monde C#).
    J'avais donc une classe ServiceLocator qui contient un membre statique std::map<string, void*> avec 2 methodes statiques Register et GetService. Lorsque je l'utilisais dans mon executable, aucun soucis. Dans la DLL.... L'opérateur [] plantais avec un "violation access memory", j'ai donc changé par la création d'un std::pair puis de faire un insert. ça fonctionnais sauf que la, j'ai l'impression que ma map statique était instancié 2 fois ! (une fois dans l'exe, une fois dans la dll et je le voyait car le nombre d'éléments dans la map était différents). Pourtant l'exe utilise la dll, donc devrais être dans le même processus, je trouve ça bizarre... J'ai donc laissé tombé car ça me prennais la tête et fais autrement mais j'aimerais bien comprendre pourquoi et utiliser une façon plus générique de faire les choses...

    2) Second cas : Je souhaitais utiliser LUA pour scripter le comportement de mon jeu de façon dynamique. Après quelques recherches, j'ai trouvé une librairie (luabind) qui me permet d'utiliser mes classes c++ dans mes scripts LUA. Cette librairie statique est incluse dans ma dll. Et là, même souffrance. Le code marche niquel dans l'exe mais dans la DLL ça plante avec une erreur R6010 (spécifique à LUA peut-être) au code c++ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    luabind::module(state) [
        luabind::class_<MyClass>("MyClass")
          .def(luabind::constructor<int>())
          .def("print", &MyClass::print)
    Encore une histoire de template semblerait...

    Dans tout ça, j'ai l'impression que l'utilisation de template est réservé uniquement aux executables mais ça me gêne car j'aimerais encapsuler certains comportements et découpler la partie jeu (executable) de la partie métier (librairie). Je ne souhaite pas faire un gros executable de 50Mo et pouvoir découper mes parties comme j'aurais pu le faire en C# et j'aimeria spouvoir réutiliser mon moteur pour faire un editeur de niveau par exemple. Ma question est de savoir si mon approche est bonne en c++ et s'il est interdit d'utiliser les templates dans les librairies, si c'est mon compilateur vc++ 2013 qui est bugué ou si il y a quelque chose de particulier pour utiliser les templates dans les librairies...

    Je trouve beaucoup de documentation sur les templates mais pas vraiment grand chose sur leur utilisation dans des librairies.


    Merci par avance pour vos réponses

  2. #2
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    membre statique std::map<string, void*>


    Déjà, les statiques c'est le mal, et tu en rencontres une des causes : les DLL sont dans leur propre espace mémoire donc tes statiques sont bel et bien instanciées 2 fois : dans l'appli et dans la DLL.
    Ensuite les void* c'est le mal, en C++ il y a toujours moyen de faire mieux (avec le polymorphisme, par exemple).

    Par rapport à ton problème, évite les variables statiques et ça devrait mieux se passer.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  3. #3
    Membre éclairé Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Par défaut
    Merci pour ta réponse

    Si je comprend bien, il faut pas utiliser les statiques mais comment implémenter correctement un servicelocator ? Le pattern (comme je l'utilise en c#) est constitué d'une map (dictionnary) statique qui stocke les objets que l'ont à enregistré et qui permet de les recuperer facilement avec un getter. Du coup, si je souhaite exposer une classe abstraite (interface) sur mon getter dans mon executable IElement et définir le service avec mon implémentation MyElement. de façon que :

    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
     
    DLL :
    // Methode init du moteur...
    {
    ...
    Locator::Register<IElement>(new MyElement());
    ...
    }
     
    EXE :
    {
    ...
    IElement *tata = Locator::Resolve<IElement>();
    ...
    }
    on peux pas le faire ?

    Autre element, tu me dis qu'il ne faut pas utiliser les void*, cependant, imaginont le cas suivant :
    - Ma librairie utilise une autre librairie X.
    - X contient une classe Y.
    Dans ma dll, j'ai un .h tel que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class Test
    {
    public:
    inline Test() { m_tata = new Y(); }
    virtual ~Test() {}
    private:
    Y *m_tata;
    }
    - Dans mon exe j'ai besoin de Test, donc je met à dispo test.hpp.
    - Dans l'exe j'aurais donc besoin de Y.hpp car test.hpp l'utilise.

    Comment puis-je encapsuler m_tata de façon à ce que l'executable n'ai pas besoin de Y ? à part le void* et un static_cast<> dans le .cpp je ne vois pas comment faire autrement

    Merci !

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Pourquoi le locator aurait besoin d'être global alors qu'il suffirait que l'application crée le sien ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre éclairé Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Par défaut
    Oui effectivement mais ce que je fais (possible que ça soit pas bon ) :

    - main crée Engine puis l'initialize.
    - Dans la méthode d'initialisation, Engine va enregistrer ses différents services qui vont êtres utilisé un peu partout (ResourceManager ec...). Je dois pouvoir réutiliser les resources déjà existante.

    Dans l'application, j'en ai aussi besoin car si je veux charger une ressource (une image par exemple), j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Resource *res = Locator::Resolve<ResourceManager>().Load("myPicture.png");
    Si je crée un text dans la dll (affichage du fps), je dois pouvoir réutiliser la ressource dans un autre objet dans l'exe (afficher un "coucou"). Dans mon cas, si je dois utiliser 2 fois "myPicture.png", je devrais avoir 2 reference sur le pointeur de ma ressource et pas charger 2 fois la ressource même si elle a une référence dan sla dll et une autre dans l'exe.

    Si je devais l'instancier, et avoir qu'une seule instance, j'aurais 2 choix :
    - Créer un singleton de Locator => Locator::getInstance()-><ResourceManager>().Load("myPicture.png"); => pas pratique en écriture et ça retire l'interet du servicelocator. autant faire des getter pour chaque service.
    - Passer Engine partout. => lourd à gerer et pas forcément utile dans toute les méthodes...

    Après, comme je disais, si je souhaite que le moteur m'initialize les services et que je puisse les utiliser aussi bien dans la dll que dans l'exe. ça peux vous paraitre bizarre mais je fais comme ça en C# quand j'en ai besoin. Après, comme je le disais, je suis novice en c++ et j'essaye peut-être d'adapter une façon de faire d'un autre langage qui n'est pas adapté en c++.

    Comment vous y prennez-vous dans ce cas ? Vous créer tout dans l'exe puis vous le passer à chaque fois? j'ai pas envie de devoir fournir une api ou on dois renseigner 50 lignes avant de pouvoir utiliser quelque chose... enfin... c'ets mon souhait, après faudra que je m'adapte au langage

    Merci !

  6. #6
    Membre éclairé Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Par défaut
    J'ai bien réfléchit et je me pose une question :

    ça vous semblerait pertinent de créer une classe Locator qui contiendrais la map le register et le resolve mais qui serais un membre de engine ? Du coup, il faudrait que je passe l'instance de engine à chaque component pour avoir accès aux services. Ca ne dois pas être couteux en mémoire d'avoir un pointeur / classe... (Je suis toujours dans une recherche de solution pour arriver à utiliser mes templates et éviter les erreurs en retirant les static car vous m'avez dit que c'est pas bien de les utiliser... ).

    Du coup, pour mes singletons (qui ont l'air de marcher) je fais comment si j'ai plus de statique? ça deviens prise de tête tout ça

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

Discussions similaires

  1. question concernant les fichier.bin
    Par argon dans le forum Autres Logiciels
    Réponses: 10
    Dernier message: 27/08/2005, 17h44
  2. Questions concernant les études supérieures et travails
    Par Vivian Pennel dans le forum Etudes
    Réponses: 25
    Dernier message: 21/06/2005, 15h23
  3. Réponses: 11
    Dernier message: 21/06/2005, 10h16
  4. [Débutant] Deux questions concernants les vues
    Par 13obscur dans le forum Eclipse Platform
    Réponses: 1
    Dernier message: 19/04/2005, 14h29
  5. Réponses: 7
    Dernier message: 10/09/2004, 14h28

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