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 :

Nouvelle bibliothèque libre de réflexion pour C++ [Nouveauté]


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut Nouvelle bibliothèque libre de réflexion pour C++
    Bonjour à tous

    Tegesoft vient de publier la première version publique de CAMP, une bibliothèque libre permettant d'étendre les classes C++ pour leur donner des capacités d'introspection.

    CAMP permet de binder classes, propriétés, fonctions et objets de manière complètement non-intrusive, afin de pouvoir les manipuler de manière homogène en runtime. Cela permet par exemple d'utiliser ses propres classes dans des scripts (Python, Lua, ...), de les sérialiser automatiquement via des formats textuels ou binaires, de les envoyer sur le réseau, de construire des éditeurs de propriétés, etc.

    Le système est fortement inspiré de boost.python ou encore de luabind, sauf qu'il est plus abstrait et peut ensuite être exploité pour n'importe quelle utilisation, pas seulement dans un cadre particulier (un langage de script pour les exemples cités).

    CAMP est distribué sous licence LGPL v3.

    Un petit exemple d'utilisation sera plus parlant qu'un long discours :
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     #include <camp/camptype.hpp>
     #include <camp/class.hpp>
     #include <string>
     #include <iostream>
     
     // Let's define a class for handling persons
     class Person
     {
     public:
     
         // Construct a person from its name
         Person(const std::string& name) : m_name(name), m_age(0)
         {
         }
     
         // Retrieve the name of a person
         std::string name() const
         {
             return m_name;
         }
     
         // Retrieve the age of a person
         unsigned int age() const
         {
             return m_age;
         }
     
         // Set the age of a person
         void setAge(unsigned int age)
        {
             m_age = age;
         }
     
         // Make a person speak (tell about its name and age)
         void speak()
         {
             std::cout << "Hi! My name is " << m_name << " and I'm " << m_age << " years old." << std::endl;
         }
     
     private:
     
         std::string m_name;
         unsigned int m_age;
     };
     
     // Make the Person type available to CAMP
     CAMP_TYPE(Person);
     
     
     int main()
     {
         // Bind our Person class to CAMP
         camp::Class::declare<Person>("Person")
             .constructor1<std::string>()
             .property("name", &Person::name)
             .property("age", &Person::age, &Person::setAge)
             .function("speak", &Person::speak);
     
         // Retrieve it by its name
         const camp::Class& metaclass = camp::classByName("Person");
     
         // Construct a new person named John
         Person* john = metaclass.construct<Person>(camp::Args("John"));
     
         // Print its name
         std::string name = metaclass.property("name").get(john);
         std::cout << "John's name is: " << name << std::endl;
     
         // Set its age to 24
         metaclass.property("age").set(john, 24);
     
         // Make John say something
         metaclass.function("speak").call(john);
     
         // Kill John
         metaclass.destroy(john);
     
         return 0;
     }

  2. #2
    screetch
    Invité(e)
    Par défaut
    ca ressemble un peu a ce que je fais
    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
    class RTTIEXPORT Test : public BugEngine::Object
    {
    private:
        int m_value;
        refptr<Test> m_other;
    public:
        Test();
        ~Test();
     
        u8& prop() const;
        void setProp(u8 value);
        void setValue(int v);
        void setValue2(const int& v);
     
        void test(const std::string& str) const;
     
        be_metaclass(RTTIEXPORT,Test,BugEngine::Object)
            void doStuff(const std::string& arg);
        be_properties
            be_property(Value)
                [be_read(m_value)]
                [be_write(m_value)];
     
            be_property(Value2)
                [be_read(m_value)]
                [be_set(setValue)];
     
            be_property(prop)
                [be_get(prop)]
                [be_set(setProp)];
     
            be_method(test);
            be_classmethod(doStuff);
        be_end
    };
    j'ai juste été embeté par le RTTIEXPORT qui est le classique declspec(dllimport)/dllexport. j'ai été obligé de le coller dans ma macro et ca c'est moche.

  3. #3
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    @screetch : ce que je trouve super avec CAMP, c'est que l'on a rien à faire depuis la classe elle-même. On pourrait faire, si l'on voulait, l'introspection de la SL avec

    Certes on doit déclarer à l'engine les attributs/fonctions qu'on veut "introspecter", mais ça peut se faire à l'extérieur. C'est possible aussi avec ton code d'introspection ?

  4. #4
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    C'est du très beau travail. Plus le temps passe et plus je me dis que le C++ a de moins de chose à envier à Java du coté introspection/choses dynamiques.

    Mais il me reste une question (de noob): en pratique, a quoi ca peut servir ?(l'introspection en général).

    Merci.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    Mais il me reste une question (de noob): en pratique, a quoi ca peut servir ?(l'introspection en général).
    J'avoue que je me le demande aussi.

    Si quelqu'un avait une explication simple avec un exemple concret à proposer, je lui en serait éternellement reconnaissant.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    L'autre bibliothèque de Tegesoft, GICS, utilise CAMP.
    Cf :
    Dependencies Qt >= 4.5.0
    CAMP >= 0.6.0
    http://www.tegesoft.com/products/gics

  7. #7
    Membre très actif
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    J'avoue que je me le demande aussi.

    Si quelqu'un avait une explication simple avec un exemple concret à proposer, je lui en serait éternellement reconnaissant.
    exemple le designer d'un framework graphique type qt, utilise l'introspection pour afficher le volet des propriétés pour chaque widget

  8. #8
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Alp Voir le message
    @screetch : ce que je trouve super avec CAMP, c'est que l'on a rien à faire depuis la classe elle-même. On pourrait faire, si l'on voulait, l'introspection de la SL avec

    Certes on doit déclarer à l'engine les attributs/fonctions qu'on veut "introspecter", mais ça peut se faire à l'extérieur. C'est possible aussi avec ton code d'introspection ?
    c'est euh, possible mais un peu tordu pour l'instant. mais l'avantage du RTTI c'est que tu ne sais pas vraiment ce que tu manipules, c'est dynamique. Je ne comprends pas comment ils s'en sortent sans au moins une methode virtuelle qui te permet d'optenir la classe de l'objet ?

    dans ma bibliotheque, j'ai besoin de la classe Objet qui contient juste une methode virtuelle (qui pourrait etre pure) : metaclass(). c'est cette methode qui fait tout. De plus, une metaclasse a aussi une metaclasse ce qui permet aussi de 'introspecter; de meme une proprieté a une metaclasse, une fonction a une metaclasse. Pour l'instant les seuls trucs qui n'ont pas de metaclasse c'est les attributs (je me demande pourquoi ils ont pas de metaclasse d'ailleurs)
    la seule propriété necessaire de tous les objets du RTTI est d'avoir une metaclasse, dés qu'ils en ont une alors on peut les manipuler.

    Dans l'exemple du debut, si tu envoies un objet de type Person a un script, sans connaitre son type exact, comment fais tu pour le manipuler (sachant que si ca se trouve c'etait une instance de Client)

  9. #9
    screetch
    Invité(e)
    Par défaut
    sinon aussi, pour les idées d'utilisation, moi j'avais couplé Mono avec mon RTTI, et Lua est couplé depuis un moment, et j'avais couplé Gtk aussi, ce qui me permettait depuis Lua de créer des fenetres GTK et d'appeler des methodes ecrites en C#

    le RTTI est un noeud central qui permet de faire circuler beaucoup d'informations; tout les trucs qui se branchent dessus peuvent communiquer ensemble; c'est vraiment très puissant

  10. #10
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Je ne comprends pas comment ils s'en sortent sans au moins une methode virtuelle qui te permet d'optenir la classe de l'objet ?
    C'est la macro CAMP_TYPE qui associe un identificateur à la classe, de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define CAMP_TYPE(type) \
                template <> struct StaticTypeId<type> \
                { \
                    static const char* get() {return #type;} \
                }; \
    Ensuite on récupère très simplement l'identificateur CAMP d'un objet comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    const char* staticTypeId(const T&)
    {
        return StaticTypeId<T>::get();
    }
    Puis sa metaclasse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    const Class& classByObject(const T& object)
    {
        return detail::ClassManager::instance().getById(staticTypeId(object));
    }
    (le code a été volontairement simplifié, il y a dans le vrai code diverses feintes en plus pour pallier certains problèmes tordus, ainsi que d'autres surchages / variantes pour gérer tous les cas possibles)

    Il y a toutefois une situation où l'on doit introduire une fonction virtuelle dans la classe (masquée par une macro) : c'est dans le cas de hiérarchies de classes, si l'on veut que CAMP puisse exploiter les notions de parenté (ie. récupérer la metaclasse du type dérivé en passant un pointeur sur classe de base).

    Dans l'exemple du debut, si tu envoies un objet de type Person a un script, sans connaitre son type exact, comment fais tu pour le manipuler (sachant que si ca se trouve c'etait une instance de Client)
    Je ne suis pas sûr de comprendre. Au moment où tu l'envoies au script tu connais son type, soit via son type statique C++ soit via sa metaclasse si tu ne peux plus trimballer son type statique. CAMP définit une classe pour ça : camp::Object, qui contient le pointeur vers l'objet plus sa metaclasse.

  11. #11
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Cool, CAMP risque de m'intéresser aussi à terme

    A propos du fameux code déclaratif :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
         // Bind our Person class to CAMP
         camp::Class::declare<Person>("Person")
             .constructor1<std::string>()
             .property("name", &Person::name)
             .property("age", &Person::age, &Person::setAge)
             .function("speak", &Person::speak);
    Je trouve que c'est bien car cela permet de choisir finement le niveau d'exposition de la classe aux méta-données.

    Par contre, ça serait bien si on avait aussi une macro pour le faire tout seul dans certain cas.

    Du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CAMP_TYPE(Person);
    CAMP_DECLARE_PUBLIC_METHODS(Person);
    CAMP_DECLARE_PRIVATE_FIELDS(Person);
    Ou quelque chose dans l'idée.

  12. #12
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Et comment cette macro connaîtrait-elle les fonctions et membres à déclarer ?

  13. #13
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    +1
    Surtout qu'il y a des membres public ou privés sans getter que l'on se souhaite pas exposer...
    Qui plus est, tu peux aussi documenter à la manière des docs_string de Boost.Python grâce au tag, genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    camp::Class::declare<CBlobMerging>("CBlobMerging")
    		.tag("help", "test")
    		.base<IVisionModule>()
    		.constructor0()
    		.property("orientation",	&CBlobMerging::m_orientation).tag("property", "Orientation of the box")
    		.property("distance",		&CBlobMerging::m_distance).tag("property", "Distance between two boxes")
    		.property("input",			&CBlobMerging::m_input_name).tag("input", "List of Bounding Boxes")
    		.property("output",			&CBlobMerging::m_output_name).tag("output", "List of Bounding Boxes");
    Du coup, pas de miracle, il faut tout faire à la main !

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Citation Envoyé par poukill Voir le message
    +1
    Surtout qu'il y a des membres public ou privés sans getter que l'on se souhaite pas exposer...
    Je suis d'accord, mais dans ce cas il suffit de ne pas utiliser la macro et de déclarer à la mano (je rejoins mon post précédent ou je dis que c'est bien pour gérer l'exposition finement).

    Quant à comment une telle macro trouve les membres à déclarer, ça dépend de ta question :
    - Si c'est quels membres choisir ? Ben par exemple, toutes les méthodes publiques (CAMP_DECLARE_PUBLIC_METHODS).
    - Si c'est comment techniquement ? C'est le boulot de la lib je dis pas que c'est facile.

  15. #15
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    - Si c'est comment techniquement ? C'est le boulot de la lib je dis pas que c'est facile.
    Je pense bien que c'est impossible, sauf si C++ peut énumérer. J'en doute.

Discussions similaires

  1. SplatGL : une nouvelle bibliothèque de rendu Python pour les jeux 2D
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 0
    Dernier message: 01/11/2014, 16h38
  2. Mantle : une nouvelle bibliothèque graphiques pour mieux contrôler le GPU
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 5
    Dernier message: 15/11/2013, 11h51
  3. Bibliothèque (libre) pour site social
    Par ymoreau dans le forum Bibliothèques et frameworks
    Réponses: 6
    Dernier message: 08/06/2011, 18h05
  4. Réponses: 3
    Dernier message: 20/06/2006, 07h06

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