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

Mon programme Discussion :

[OpenSource][C++] Wrapper C++ pour Lua


Sujet :

Mon programme

  1. #1
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut [OpenSource][C++] Wrapper C++ pour Lua
    Bonjour à tous,

    Voilà plusieurs années que je programme différents projets dans lesquels j'ai besoin d'un langage de script. Après quelques recherches, mon choix c'est tourné vers Lua, principalement pour sa syntaxe proche de celle du C++ et pour sa simplicité.

    Le seul soucis, c'est que Lua a été programmé en C. Autant la syntaxe du langage est simple, autant son interface en C est relativement pénible à utiliser, même si je doute que l'on puisse faire beaucoup mieux.
    J'ai donc pris le temps d'écrire un wrapper en C++ dont le but est d'encapsuler tous les appels de fonctions C de Lua et qui tire profit des capacités du C++. Pour le moment, seule une partie des fonctions de la bibliothèque originale sont supportées, mais je n'ai pas encore éprouvé le besoin d'utiliser les autres De plus, il reste possible à tout moment de récupérer un pointeur vers la lua_State sous-jacente et d'utiliser comme on le souhaite les fonctions C dessus. En bref : que du bonus. Les sources ci-dessous contiennent donc une classe "centrale", qui wrappe le pointeur vers la lua_State. Elle est sobrement nommée lua::state.

    Mais ce n'est pas tout ! On a très souvent besoin d'ajouter des fonctions supplémentaires au langage Lua, qui font appel à des fonctions du programme qu'on développe. On appelle ça des "glues". Le principe est assez simple (les arguments de la fonction sont déposés en haut du stack Lua, on les lit, puis on pousse les valeurs de retour sur le stack, que Lua gère ensuite), mais est très sujet aux erreurs. En particulier, le gestion des types d'entrée peut être pénible. J'ai donc également programmé une classe utilitaire nommée lua::function qui se charge de tout : vérification des types en entrée, gestion des valeurs de retour, etc. La syntaxe est je pense assez simple :
    Code c++ : 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
    80
    // La signature obligatoire des "glues"
    int set_texture(lua_State* pLua)
    {
        // On créé d'abord la classe d'aide.
        // Le nom sera utilisé pour les messages d'erreurs.
        // Le nombre à la fin spécifie le nombre total de
        // valeurs que la fonction est sensée retourner.
        // Si vous en donnez moins, la fonction complètera
        // elle même avec des 'nil' (ce paramètre peut être
        // ommis).
        lua::function mFunc("set_texture", pLua, 2);
     
        // ... puis on définit les paramètres qu'on attend.
        // Par exemple ici, on peut prendre soit une chaine :
        mFunc.add(0, "texture", lua::TYPE_STRING);
     
        // ... ou,
        mFunc.new_param_set();
        // ... quatre nombres,
        mFunc.add(0, "red",   lua::TYPE_NUMBER);
        mFunc.add(1, "green", lua::TYPE_NUMBER);
        mFunc.add(2, "blue",  lua::TYPE_NUMBER);
        // ... dont un qui est optionel.
        mFunc.add(3, "alpha", lua::TYPE_NUMBER, true);
        // Eventuellement, si on a une grande liste d'arguments
        // et qu'on veut que le Xième puisse prendre deux
        // types différents, on a le droit d'écrire :
        mFunc.add(X, "blabla", lua::TYPE_STRING);
        mFunc.add(X, "blabla", lua::TYPE_NUMBER);
        // Il faudra alors vérifier soi-même le type obtenu.
     
        // On vérifie ensuite si les paramètres sont bons.
        if (mFunc.check())
        {
            // On regarde quel set de paramètre a été fourni
            if (mFunc.get_param_set_rank() == 0)
            {
                // Puis on extrait les données en conséquence
                std::string name = mFunc.get(0)->get_string();
     
                // [...]
            }
            else
            {
                color mColor;
     
                // Ici on regarde si le paramètre optionnel a été fourni
                if (mFunc.is_provided(3))
                {
                    mColor = color(
                        mFunc.get(3)->get_number(),
                        mFunc.get(0)->get_number(),
                        mFunc.get(1)->get_number(),
                        mFunc.get(2)->get_number()
                    );
                }
                else
                {
                    mColor = color(
                        mFunc.get(0)->get_number(),
                        mFunc.get(1)->get_number(),
                        mFunc.get(2)->get_number()
                    );
                }
     
                // [...]
            }
        }
     
        // Ensuite on envoie deux valeurs :
        double toto = 1.0;
        mFunc.push(toto);
        std::string pouet = "hello";
        mFunc.push(pouet);
     
        // ... et on termine en appelant on_return,
        // qui retourne simplement le nombre total de
        // valeurs retournées, comme Lua le veut.
        return mFunc.on_return();
    }

    Le tout vient avec un type variant lua::var qui permet de stoker dans une même variable C++ un objet de type nombre, string, booléen, ou autre, ce qui simplifie grandement la vie dans certains cas (le code est inspiré de la classe "variant" présentée sur ce site !). Les deux autres classes supportent ce type nativement.

    Pour finir, j'ai aussi inclus un petit bout de code qui n'est pas de moi, nommé "Lunar", qui permet de gérer des classes en parallèle entre Lua et C++ de manière assez simple. Je n'ai pas trouvé de version mise à jour, et je n'ai pas les connaissances nécessaires en Lua pour l'upgrader. À noter donc : tout le code est compatible avec Lua 5.1.4, mais par la 5.2 !

    Voilà pour la présentation, je pense n'avoir rien oublié.
    Dans la version pré-compilée, vous trouverez un dossier "doc" avec la documention doxygen pré-générée. Les commentaires sont de toute façon toujours dans les sources, donc vous pouvez la générer vous même si vous le souhaitez.
    Le tout se compile en principe sans problème avec MinGW sous Windows ou avec g++ sous Linux, en activant le support du C++11 (nécessite gcc 4.5 au minimum). Les projets de compilation pour Code::Blocks sont fournis, mais rien de plus. La bibliothèque "luapp" se base sur une petite bibliothèque utilitaire "utils" qu'il faudra aussi compiler (elle propose un pointeur à compteur de référence et son weak pointer associé, quelques fonctions raccourcis pour la gestion des fichiers et des chaînes de caractères).
    C'est open source et libre, distribué sous licence GNU.
    J'espère que ça pourra servir à d'autres !

    Normalement, le tout est bien rôdé puisque je m'en sers depuis longtemps. Seulement, j'ai commencé a me servir d'un framework un peu lourdingue dont j'essaye maintenant de me passer. J'ai donc dû re-traduire tout pour éliminer les dépendances. En conséquence, il peut y avoir quelques accrocs, mais rien de trop grave je pense.
    N'hésitez pas à intervenir ici si vous avez des soucis ou si certains points ne sont pas clairs.

    Les fichiers, pour la v1.000 :
    • bibliothèque pré-compilée (mingw32) + sources + doc : [7z] (456 Ko) ou [zip] (1379 Ko)
    • sources seulement : [7z] (34 Ko) ou [zip] (46 Ko)

  2. #2
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Août 2008
    Messages
    26 618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 26 618
    Points : 188 591
    Points
    188 591
    Par défaut


    À mon avis, tu ne devrais pas hésiter à la proposer dans l'application de téléchargements (au moins rubrique C++) : http://cpp.developpez.com/telecharge...e/96/Sources-C.
    Vous souhaitez participer aux rubriques Qt (tutoriels, FAQ, traductions) ou HPC ? Contactez-moi par MP.

    Créer des applications graphiques en Python avec PyQt5
    Créer des applications avec Qt 5.

    Pas de question d'ordre technique par MP !

  3. #3
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Pourquoi pas. Voilà qui est fait : click !
    Je n'ai pu uploader qu'un seul fichier, je me suis donc contenté de mettre les sources dans une archive .zip. Ça devra suffire

  4. #4
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Après quelques semaines d'utilisations, voici la version corrigée. J'espère qu'il ne reste aucun bug !

    Les fichiers, pour la v1.001 :
    • bibliothèque pré-compilée (mingw32) + sources + doc : [7z] (451 Ko) ou [zip] (1395 Ko)
    • sources seulement : [7z] (29 Ko) ou [zip] (48 Ko)

  5. #5
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Pas de changement fondamental dans cette dernière version. Quelques améliorations du code (interdiction de la copie sur certaines classes qui n'ont pas vocation à être copiées), et de la documentation (maintenant aussi inclue avec le code source).

    À noter : la licence est passée de GNU GPL à GNU LGPL (vous pouvez utiliser la bibliothèque dans votre programme quelle qu'en soit la licence, mais si vous modifiez ma bibliothèque, vous devez rendre publics les changements effectués).

    Les fichiers, pour la v1.004 :
    • bibliothèque pré-compilée (mingw32) + sources + doc : [7z] (449 Ko) ou [zip] (765 Ko)
    • sources + doc seulement : [7z] (101 Ko) ou [zip] (227 Ko)

  6. #6
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Petite maintenance:
    • ajout des projets de compilation pour Visual C++ 2010
    • correction mineures de const-correctness, variable non initialisée et conversions dangereuses entre entiers signés et non signés


    Les fichiers, pour la v1.005 :
    • bibliothèque pré-compilée (mingw32) + sources + doc : [7z] (467 Ko) ou [zip] (792 Ko)
    • bibliothèque pré-compilée (visual studio 2010) + sources + doc : [7z] (539 Ko) ou [zip] (1116 Ko)
    • sources + doc seulement : [7z] (106 Ko) ou [zip] (239 Ko)

Discussions similaires

  1. [JNA] Faire un wrapper java pour une application C
    Par danim dans le forum Entrée/Sortie
    Réponses: 9
    Dernier message: 30/10/2008, 16h04
  2. [Interop] Wrapper .NET pour les API Windows ?
    Par tomlev dans le forum C++/CLI
    Réponses: 3
    Dernier message: 31/03/2008, 10h31
  3. Un forum réservé pour Lua
    Par zuzuu dans le forum Evolutions du club
    Réponses: 5
    Dernier message: 18/02/2008, 15h24
  4. Enregistrer des callback pour LUA
    Par aiolia_aiolos dans le forum Développement 2D, 3D et Jeux
    Réponses: 1
    Dernier message: 24/07/2007, 11h06
  5. Programme C++ de console pour Lua
    Par Xitog dans le forum C++
    Réponses: 1
    Dernier message: 30/05/2007, 19h46

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