Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 6 sur 6
  1. #1
    Membre expérimenté

    Homme Profil pro
    Doctorant en astrophysique
    Inscrit en
    juin 2007
    Messages
    360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en astrophysique

    Informations forums :
    Inscription : juin 2007
    Messages : 360
    Points : 535
    Points
    535

    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++ :
    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

    Avatar de dourouc05
    Homme Profil pro Thibaut Cuvelier
    Étudiant
    Inscrit en
    août 2008
    Messages
    19 337
    Détails du profil
    Informations personnelles :
    Nom : Homme Thibaut Cuvelier
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : août 2008
    Messages : 19 337
    Points : 74 963
    Points
    74 963

    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 ou PyQt/PySide (tutoriels, FAQ, traductions, sources) ? Contactez-moi par MP.

    Créer des applications avec Qt 5.

    Pas de question d'ordre technique par MP !

  3. #3
    Membre expérimenté

    Homme Profil pro
    Doctorant en astrophysique
    Inscrit en
    juin 2007
    Messages
    360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en astrophysique

    Informations forums :
    Inscription : juin 2007
    Messages : 360
    Points : 535
    Points
    535

    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 expérimenté

    Homme Profil pro
    Doctorant en astrophysique
    Inscrit en
    juin 2007
    Messages
    360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en astrophysique

    Informations forums :
    Inscription : juin 2007
    Messages : 360
    Points : 535
    Points
    535

    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 expérimenté

    Homme Profil pro
    Doctorant en astrophysique
    Inscrit en
    juin 2007
    Messages
    360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en astrophysique

    Informations forums :
    Inscription : juin 2007
    Messages : 360
    Points : 535
    Points
    535

    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 expérimenté

    Homme Profil pro
    Doctorant en astrophysique
    Inscrit en
    juin 2007
    Messages
    360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en astrophysique

    Informations forums :
    Inscription : juin 2007
    Messages : 360
    Points : 535
    Points
    535

    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)

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •