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 autresDe 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 :
Partager