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 :

Intégration de scripts lua


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut Intégration de scripts lua
    Bonjour,
    Je travaille actuellement sur un petit projet pour tester différentes manières de rendre un programme plus modulaire : plugins, scripts, …
    Le programme en lui-même est plutôt simple : il s'agit d'un jeu de cartes (dans le style des cartes Magic). Chaque carte peut être soit une créature, soit un sort. Si c'est un sort, elle dispose d'une seule action (le sort en question). Si c'est une créature, elle dispose de plusieurs (mais le nombre est défini). De plus, chaque carte dispose de certaines propriétés communes telles que le nom, description, niveau, …

    Je cherche donc à implémenter chaque carte sous forme de plugins, scripts en différents langages, … afin d'avoir quelque chose le plus modulaire possible. Voilà ma classe Carte, toute simple :
    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
    class Carte {
    public:
     
    	enum Type {
    		Creature,
    		Sort,
    		Indefini,
    	};
     
    	Carte();
    	virtual ~Carte();
    	virtual void debutTour();
    	virtual void invocation();
    	virtual void mort();
    	virtual int niveau() const;
    	virtual int pv() const;
    	virtual int pvMax() const;
    	virtual std::string nom() const;
     
    private:
    	int		m_niveau;
    	int		m_pv;
    	int		m_pvMax;
    	Type		m_type;
    	std::string	m_nom;
    	Joueur*		m_prop;
    	Joueur*		m_adversaire;
    };
    Chaque méthode est définie vide dans le cpp, sauf les accesseurs, toutes les cartes n'ayant pas besoin de réimplémenter chacune des actions. Ces méthodes sont appelées automatiquement par le reste du programme.

    J'ai commencé deux «chargeurs» de cartes : un sous la forme de plugins (en C++), qui avance bien et ne me pose pas de problème particulier. Le second consiste à charger un script lua définissant une carte. Dans un premier temps, je cherche à simplement définir les propriétés «basiques», et non les actions. J'étais parti sur l'exemple présenté ici. J'arrive à faire dans un script lua une classe qui dérive de Carte, et y appeler des méthodes… Mais c'est là que je me rends compte d'un gros soucis sur mon raisonnement : je n'ai aucun moyen de récupérer cette carte dans mon code C++ (du moins, je n'en ai pas trouvé).

    Et là, je sèche… Je ne vois pas comment définir une classe en lua, qui contienne les mêmes propriétés qu'une classe C++, et la récupérer en C++.

    Si quelqu'un à la moindre piste, je suis preneur !
    Merci.

  2. #2
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Une bonne manière de faire est d'avoir dans ton LUA des *fonctions* qui correspondent aux méthodes de ton instance car bindé une LUA function est assez triviale

    Chaque instance de ta classe C++ est construite en chargant un LUA qui contient une fonction par méthode de la classe.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut
    Bonjour,
    Suite à quelques petits soucis de connexion internet, j'ai pas vraiment pu mettre ce topic à jour… Chose que je vais corriger tout de suite.
    Déjà, Joel F, merci de ta réponse Cependant, je n'ai pas pu la voir, et j'ai continué le développement à côté, je suis parti sur une autre piste.
    Avec luabind, j'ai réussi à instancier en lua une classe qui hérite de ma classe Carte, et à récupérer une instance, sous la forme de Carte*, en C++. Tout le code de cette partie est accessible ici. Mon code marche parfaitement pour une ou deux cartes… Jusqu'à 7, en fait. Mais dès que je charge une 8° carte, l'appel à luaL_dofile me fait une jolie erreur de segmentation.

    Voici la structure d'une carte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class 'ForestSpirit' (carte)
     
    function ForestSpirit:__init()
        carte.__init(self)
    end
     
    function ForestSpirit:test()
        print('ForestSpirit:test()')
    end
     
    a = ForestSpirit()
    Et la callstack :
    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
    #0  0x0000000000000051 in ?? ()
    #1  0x00007ffff69c5997 in std::auto_ptr<LuaWrapper>::~auto_ptr() () from ./libCore.so
    #2  0x00007ffff69c5b7b in luabind::detail::pointer_holder<std::auto_ptr<LuaWrapper>, LuaWrapper>::~pointer_holder() () from ./libCore.so
    #3  0x00007ffff5d09561 in luabind::detail::object_rep::~object_rep() () from /usr/lib/libluabind.so.0.9.0
    #4  0x00007ffff5d09602 in luabind::detail::destroy_instance(lua_State*) () from /usr/lib/libluabind.so.0.9.0
    #5  0x00007ffff5f1dff1 in luaD_precall () from /usr/lib/liblua.so.5
    #6  0x00007ffff5f1e473 in luaD_call () from /usr/lib/liblua.so.5
    #7  0x00007ffff5f1fc4e in GCTM () from /usr/lib/liblua.so.5
    #8  0x00007ffff5f1fd5c in singlestep () from /usr/lib/liblua.so.5
    #9  0x00007ffff5f20290 in luaC_step () from /usr/lib/liblua.so.5
    #10 0x00007ffff5f1d854 in f_parser () from /usr/lib/liblua.so.5
    #11 0x00007ffff5f1db77 in luaD_rawrunprotected () from /usr/lib/liblua.so.5
    #12 0x00007ffff5f1dbde in luaD_pcall () from /usr/lib/liblua.so.5
    #13 0x00007ffff5f1dca2 in luaD_protectedparser () from /usr/lib/liblua.so.5
    #14 0x00007ffff5f19798 in lua_load () from /usr/lib/liblua.so.5
    #15 0x00007ffff5f2982d in luaL_loadfile () from /usr/lib/liblua.so.5
    #16 0x00007ffff69bc8e0 in ChargeurLua::instancierCarte(std::string const&) () from ./libCore.so
    Petite précision : LuaWrapper est une classe héritant de Carte qui me permet de faire l'interface entre une classe lua et du code C++, c'est ce que je récupère via luabind.

    J'ai essayé avec plusieurs cartes différentes, dans un ordre différent, il plante toujours sur la 8°.
    En mettant un print('test') au début de chaque fichier lua chargé, il est affiché sur les 7 premiers, mais pas du tout sur le 8°.
    Il y a quelque chose à faire de particulier avec lua pour lui faire réserver plus de mémoire ou autre ? Ça fait plusieurs jours que je cherche dans la doc' et autres, je sèche…

  4. #4
    Membre averti Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Points : 302
    Points
    302
    Par défaut
    Hello,
    J'avais eu la même idée que toi à une époque (jeu de Magic) mais j'avais directement commencé par la partie graphique bien violente pour me former à OpenGl
    Pour le langage de script, il est également très facile d'interfacer Python et C++ avec boost.python. Je m'en sert dans mon boulot et ce n'est vraiment que du bonheur. Le mélange Python/C++ via boost.python est déjà utilisé dans l'industrie du jeu vidéo notamment dans Civilisation 4 et 5 (donc pas n'importe quoi).

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut
    J'ai aussi songé à de l'OpenGL pour la partie graphique, mais j'ai finalement opté pour une autre approche : je développe pour le moment une librairie qui ne dépend de rien de graphique, et une petite interface graphique avec Qt pour tester ça rapidement, l'interface est loin d'être définitive, je connais juste plutôt bien Qt, donc j'en profite. Au moins, celà me permet de me concentrer sur le jeu en lui même… Et mes problèmes de lua

    J'avais remarqué Boost.python oui, mais ce dernier attendra que je puisse charger une carte lua. En attendant, j'ai terminé le chargement de cartes sous la forme de plugins C++. J'ai pas testé les plugins statiques, mais les plugins dynamiques marchent comme sur des roulettes. C'est surtout ce problème de lua qui m'embête…

    (Si l'idée du projet t'intéresse toujours, on peut en parler en mp pour une interface en OpenGL )

  6. #6
    Membre averti Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Points : 302
    Points
    302
    Par défaut
    (Si l'idée du projet t'intéresse toujours, on peut en parler en mp pour une interface en OpenGL )
    Arf, j'ai abandonné le projet il y a fort (fort) longtemps. Surtout que j'ai plus du tout le temps pour l'instant.

    J'avais remarqué Boost.python oui, mais ce dernier attendra que je puisse charger une carte lua. En attendant, j'ai terminé le chargement de cartes sous la forme de plugins C++. J'ai pas testé les plugins statiques, mais les plugins dynamiques marchent comme sur des roulettes. C'est surtout ce problème de lua qui m'embête…
    Ça semble planter à std::auto_ptr<LuaWrapper>::~auto_ptr(), donc surement sur un delete appelé sur un pointeur non initialisé ou déjà désalloué. Ça doit dépendre de la manière dont tu manipule tes Carte*. Ou alors les Carte* stockées sont trop grosses et le 8ème appel à new lève une exception que tu n'attrape pas (ou un malloc qui retourne NULL). Bref je connais pas Lua donc...

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut
    Je commence par générer une liste de cartes valides :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void ChargeurLua::genererListeCartes() {
        std::vector<std::string> fichiersLua;
        boost::filesystem::path chemin = boost::filesystem::initial_path() / "lua";
        iterDir(chemin, fichiersLua);
     
        for (std::vector<std::string>::const_iterator it = fichiersLua.begin(); it != fichiersLua.end(); ++it) {
            Carte* carte = instancierCarte(*it);
            if (carte) {
                m_nom2lua.insert(std::pair<std::string, std::string>(carte->nom(), *it));
                delete carte;
            }
        }
        std::cout << "génération ok" << std::endl;
    }
    fichiersLua contenant donc la liste de tous les fichiers portant l'extension .lua.

    La méthode instancierCarte est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Carte* ChargeurLua::instancierCarte(const std::string& pLua) {
        std::cout << "pLua : " << pLua << std::endl;
        bool s = luaL_dofile(m_ls, pLua.c_str());
     
        if (s != 0) {
            std::cout << "s : " << s << std::endl;
            erreursLua(s);
            return NULL;
        } else {
            Carte* carte = luabind::object_cast<Carte*>(luabind::globals(m_ls)["a"]);
            std::cout << "carte retournée : " << carte << std::endl;
            return carte;
        }
    }
    Et donc, là dedans, ça plante à l'appel à luaL_dofile… Je suppose donc qu'il y a effectivement un problème de mémoire, mais où ? Je ne sais pas.

  8. #8
    Membre averti Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Points : 302
    Points
    302
    Par défaut
    Déjà: es-tu sûr que la 8 ème carte soit valide? un appel à 'object_cast<MaClasse*>' peut renvoyer un pointeur invalide dans certains cas et attention au delete derrière...
    Concernant ce delete justement, je suis pas certain qu'il soit nécessaire. Le pointeur renvoyé par 'object_cast<MaClasse*>' référence un objet qui a été créé et qui sera détruit par luabind (enfin, si ca ressemble à boost.python, ce qui semble être le cas), mais à vérifier.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut
    Effectivement, c'est le delete qui ne lui plaisait pas… Je vais voir plus en détail pourquoi Merci !

    Edit: Ça me pose un problème en fait… L'objet n'est valide que peu de temps. Je vais voir si il n'y a pas un autre moyen de récupérer l'objet, sinon j'en ferais une copie.

  10. #10
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Novembre 2008
    Messages
    86
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2008
    Messages : 86
    Points : 355
    Points
    355
    Par défaut
    Bonjour,

    déjà, de ma propre expérience : il faut encandrer *TOUS* les appels à Lua de blocs try/catch
    (donc ici le "luaL_doFile" et les "object_cast" de globals)

    PS : Je ne connaissais pas l'opérateur "/" pour boost::path, merci bien

  11. #11
    Membre averti Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Points : 302
    Points
    302
    Par défaut
    déjà, de ma propre expérience : il faut encandrer *TOUS* les appels à Lua de blocs try/catch
    (donc ici le "luaL_doFile" et les "object_cast" de globals)
    Ça ressemble vraiment à boost.python...

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

Discussions similaires

  1. [LUA & C++] Script LUA dans un programme C++
    Par zakharorion dans le forum Autres éditeurs
    Réponses: 0
    Dernier message: 21/05/2012, 16h05
  2. Intégration de scripts oracle dans SAS
    Par mathilde_1180 dans le forum SAS Base
    Réponses: 21
    Dernier message: 08/02/2012, 17h01
  3. [Spip] intégration de script perso , Plugins.
    Par Einheijar dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 0
    Dernier message: 01/02/2011, 15h51
  4. intégration de script
    Par pm2989 dans le forum Général JavaScript
    Réponses: 14
    Dernier message: 21/01/2011, 10h35
  5. Game Scripting . [ Lua ? ]
    Par Clad3 dans le forum Développement 2D, 3D et Jeux
    Réponses: 7
    Dernier message: 21/01/2007, 12h27

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