2010-09-13 8 views
3

Je voudrais intégrer lua pour autoriser les scripts dans mon application C++. En particulier, j'ai deux structs que j'aimerais passer comme arguments à une fonction lua donnée. L'un sera en lecture seule, l'autre sera en lecture/écriture. Des exemples très simplifiés de ces struct suivent:Lecture et écriture C struct from embedded lua

struct inData 
{ 
    int x; 
    int y; 
    //many other fields follow 
}; 

struct outData 
{ 
    int a; 
    double b; 
    //other fields follow 
}; 

Ces deux struct sont créés dans le code C++ et seront traitées il y a avant et après l'appel des fonctions lua. Comment puis-je passer ces struct à une fonction Lua telle que la fonction peut faire des choses comme ceci:

if(inData.x > 5) then outData.a = 1 end 

et que l'instance OUTDATA conservent effectivement les changements après le retour de la fonction de Lua?

Répondre

6

alésage + passe-partout + multilingue = SWIG.

http://www.swig.org/Doc1.3/Lua.html#Lua_nn13

+0

Cela semble générer des wrappers pour les structures, etc. Je ne suis toujours pas clair sur le passage d'une structure existante de C vers lua. Dans l'exemple lié, la structure est instanciée dans la fonction lua, ce qui n'est pas ce que j'essaie de faire. – alanc10n

+0

Section "23.3.9 Pointeurs, références, valeurs et tableaux" traite des structures retournées créées par le code C++, soit par pointeur, soit par valeur. Cela couvre-t-il votre exigence? –

+0

Aussi http://stackoverflow.com/questions/884435/pass-variables-between-c-and-lua-via-swig Il y a actuellement pas mal de questions C++/Lua/SWIG ici sur SO, ça pourrait valoir votre temps en lire quelques-uns. –

0

Vous pouvez utiliser une userdata et y ajouter un outdata *. Vous pouvez définir des fonctions personnalisées sur eux, y compris un metatable. Je ne vais pas passer à travers parce que c'est tellement beaucoup de code. Fondamentalement, vous faites le outdata sur le tas, vous faites pointer le userdata léger (via une distribution incroyablement mauvaise), puis vous définissez un metatable personnalisé et utilisez __index pour que les accès aux données se produisent avec une fonction personnalisée. Fondamentalement, c'est faisable mais ennuyeux comme la merde. Aussi dangereux parce que Lua ne comprend aucun type C (ou C++) et que vous avez affaire à des void * s tout le temps.

+2

Un commentaire - données d'utilisateur légères [n'a pas de métadonnées individuelles] (http://www.lua.org/manual/5.1/manual.html#lua_pushlightuserdata). La méthode habituelle consiste à créer des données utilisateur complètes, de taille sizeof (void *), et contenant un pointeur vers la structure d'origine. Les données utilisateur complètes peuvent être personnalisées - le reste du commentaire s'applique, sauf pour le commentaire sur le fait d'être ennuyeux et beaucoup de code standard - dans mon expérience, c'est beaucoup mieux que dans d'autres langues. –

+0

@MikKy: Vous avez raison sur les données d'utilisateur. Il y a une raison pour laquelle j'ai arrêté d'utiliser Lua et c'est parce que l'API et les limitations de langage n'ont aucun sens. Comme pour d'autres langues, je frémirais vraiment d'imaginer ce que vous avez trouvé qui implique un code répétitif plus ennuyeux que Lua. – Puppy

1

Vous pouvez également créer une table Lua qui reflète cette même structure de données pour la transmission d'informations entre C et Lua.

+0

Donc vous suggérez de pousser chaque nom d'attribut et sa valeur sur la pile de lua pour créer une table lua, puis de les retirer et de les recopier dans la structure après le retour de la fonction? Si oui, cela semble horriblement inefficace. Si non, pourriez-vous élaborer sur cette suggestion? – alanc10n

+0

Oui, c'est ce que je suggère. En ce qui concerne les performances, cela dépend de l'utilisation. Il me semble qu'un rappel C pour accéder à chaque champ struct dans une userdata nécessiterait plus de surcoût total que de simplement copier les valeurs à l'état Lua à l'avance. –