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 :

[template] Instanciation d'une liste de types pour un plugin


Sujet :

C++

  1. #1
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut [template] Instanciation d'une liste de types pour un plugin
    Une grosse question aussi de conception que celle-ci.
    On suppose qu'on veuille créer une bibliothèque dynamique/plugin qui puisse être utilisée dans un programme global dans lequel tout type ou presque est encapsulé dans un DataObject - typiquement ITK -. Le but est de permettre d'utiliser ce plugin dans le programme avec plusieurs types de données "standards", comme int, float, double, ...
    L'appel au plugin de la bibliothèque se fait par qqch du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    plugin = new MonPlugin();
    plugin->setInput(dataObject1);
    plugin->setOuput(dataObject2);
    plugin->run()
    Lors du run(), la fonction adéquate est appelée par le run.

    Une solution que je n'aime pas trop est d'utiliser un void* avec un enum indiquant le type, et on fait un switch sur la bonne fonction à choisir. C'est pas top top au niveau maintenabilité, mais apparemment Sutter aurait proposé quelque part cette solution. Je n'ai pas réussi à retrouver cette proposition, donc si qqn peut me la donner, que je puisse l'observer...

    Une autre solution est celle qui a un temps été utilisée chez nous dans le labo. Le switch est généré automatiquement dans un en-tête sous forme de macro qu'on réutilise, la génération étant basée sur un fichier xml, le choix se faisant sur une chaîne retournée par le dataObject permettant de connaître son type.

    Maintenant, j'ai pensé à une solution plus méta-programmation. On crée un vecteur de types standards. Puis, lors du run, on fait qqch du style :
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    typedef boost::mpl::vector<int, float, double> monVecteur;
    class monPlugin
    {
    //...
    void run()
    {
      process<monVecteur>();
    }
     
    template<class vecteur>
    void process<vecteur>()
    {
      if(traits<begin<v>::type>::type() == dataObject->type()) // type() est une fonction retournant une chaîne de caractère décrivant le type, basé sur la classe traits
      {
        execute<begin<v>::type>();
      }
      else
      {
        process<pop_front<v>::type>();
      }
    }
     
    template<>
    void process<boost::mpl::vector<> >()
    {
      throw; // Erreur, type non instanciable
    }
     
    template<class Type>
    void execute<Type>()
    {
      // Execution du code du plugin
    }
    //...
    };
    Pour chaque solution, j'ai des griefs :
    - la première utilise des void* et nécessite d'utiliser des switchs à maintenir dans chaque plugin
    - la deuxième est basée sur des macros générées automatiquement, mais utilise des traits spécifique à chaque type, mais les macros sont spécifiques à un groupe de plugins pouvant travailler sur des types de données "compatibles"
    - la troisième solution nécessite d'ajouter du code dans chaque plugin - le run + les process -, mais a aussi le mécanisme commun à un groupe de plugin grâce au vecteur de types

    Est-ce que vous avez d'autres solutions ou des critiques et des préférences sur ces possibilités d'instancier automatiquement du code et de l'utiliser dans un plugin sans que l'utilisateur du plugin doive recompiler le plugin ?

  2. #2
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    ITK ? Une sorte de any/variant ?

    La solution du void*+enum, cela revient à boost::any dans mes souvenirs

    Je me trompe, ou tu as un problème de multi-dispatch dont une partie de la résolution se fait derrière ton plugin ?

    C'est marrant mpl (jamais utilisé), cela ressemble aux type_list, mais en itératif.
    A ce sujet, dans son chapitre sur le multi-dispatch, (dans Modern C++ Design) Andrei Alexandrescu avait proposé une solution à base type_list.

  3. #3
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    ITK = Insight Segmentation and Registration Toolkit
    En fait, la solution dont je parle est une surcouche du conteneur d'image d'ITK et dont on récupère principalement le ointeur sur les données + le type - mais je sens que cette solution ne marche pas si on n'utilise pas un conteneur dense -.
    Personnellement, le truc du void* ne me semble même pas suffisamment souple pour permettre élégemment d'avoir plusieurs types en même temps en entrée - style mon algo peut utiliser une image en double et une en float pour retourner une image en int par ex -

    En effet, c'est du multi-dispatch, et je veux tout cacher dans le plug-in, et surtout tout compiler pour y avoir accès

    Les type_lists de Modern C++ Design ont une séquence équivalente dans MPL mais il y a en plus d'autres séquences, comme les vectors, ...

    Effectivement, MC++D a un chaître là-dessus, je n'avais pas remarqué Merci,je vais le relire

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Utilise les templates et instancie dans ta bibliothèque les templates pour tes types.

  5. #5
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par loufoque
    Utilise les templates et instancie dans ta bibliothèque les templates pour tes types.
    Merci beaucoup pour cette réponse très éclairée, mais c'est déjà ce que je fais... Les algos sont templates, le but est de pouvoir dispatcher les données dans la bonne version de l'algo à l'exécution, comme Luc l'a remarqué, c'est du multi-dispatching.

    En gros, la version brute-force de Modern C++ Design correspond à celle que je propose en 3 à des spécificités près - Alexandrescu utilise les typeid pour faire sont dispatching par exemple -, les 2 autres sont un peu plus complexes, je ne suis pas sûr d'avoir besoin ou de réussir à utiliser efficacement les versions plus élégantes dans mon cas, à savoir wrapper des dizaines d'algorithmes...

    Au moins, personne n'utilise la première version dans ce que j'ai lu - qui est limitée aussi dans le format des données donc, on ne peut qu'utiliser des tableaux continus de données -

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Pourquoi t'utilises ton propre système au lieu des RTTI standard ?
    Le RTTI serait sûrement plus performant d'ailleurs.

  7. #7
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par loufoque
    Pourquoi t'utilises ton propre système au lieu des RTTI standard ?
    Le RTTI serait sûrement plus performant d'ailleurs.
    Parce que le type des données est connu quoiqu'il arrive :
    - On doit pouvoir les sauvegarder
    - Sur plusieurs plateformes différentes et les relire
    -> On avait ce système avant qu'on pense à étendre, donc autant le conserver - pas sûr que le RTTI soit vraiment plus performant, on a juste une fonction virtuelle, et l'avantage est qu'on peut se passe du RTTI au besoin dans certains cas -

Discussions similaires

  1. Réponses: 13
    Dernier message: 13/11/2010, 13h01
  2. vide une liste de type select
    Par naourass dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 15/04/2009, 09h05
  3. Réponses: 7
    Dernier message: 17/12/2006, 01h22
  4. Comment Manipuler des objets dans une liste de type TList ?
    Par PadawanDuDelphi dans le forum Delphi
    Réponses: 1
    Dernier message: 02/11/2006, 15h40
  5. Réponses: 2
    Dernier message: 30/06/2006, 16h46

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