J'ai un objet Lua userdata avec un certain type metatable (par exemple "stackoverflow.test"
). À partir du code C, je veux être capable de vérifier exactement de quel type il s'agit et de me comporter différemment selon les résultats. Existe-t-il une bonne fonction pratique (plutôt comme luaL_checkudata
, mais sans erreur si la réponse n'est pas ce que vous voulez) qui permettez-moi d'interroger le nom de type metatable de la userdata? Sinon, je suppose que j'ai besoin d'utiliser lua_getmetatable
, mais je ne sais pas comment déterminer le nom de la méta-donnée qui vient d'être ajoutée à la pile. Juste pour clarifier: j'utilise Lua 5.1, où le comportement de luaL_checkudata a été changé. Je comprends que dans 5.0, il n'a pas l'habitude d'erreur.Demande le type Lua userdata à partir de C
Répondre
Vous allez utiliser lua_getmetatable
et lua_equal
pour les tests que les tables sont les mêmes. À mon avis, Lua devrait donner plus de soutien à ce genre d'extension de type. A partir de maintenant, c'est vraiment la responsabilité du système d'encapsulation Lua/C (++) de le faire.
Dans un emballage que j'ai fait récemment (dans le cadre d'un projet commercial), je fais class::instance(L,index)
pour obtenir des pointeurs userdata d'un type particulier. En d'autres termes, cette méthode vérifie que c'est userdata et que la métatable est également correcte. Sinon, il renvoie NULL.
La façon dont Lua pourrait aider tout ceci est que la métatable ait un champ standard pour les informations de type étendu (c'est-à-dire __type
). Cela pourrait être utilisé de sorte que type()
lui-même retournerait "userdata", "xxx" (deux valeurs, n'en renvoyant actuellement qu'une seule). Cela resterait compatible avec la plupart du code actuel. Mais c'est juste hypothétique (à moins que vous ne fassiez un type personnalisé() et l'implémentez vous-même).
Je viens de regarder le code source à la fonction luaL_checkudata
, et il récupère fondamentalement la métatable de l'objet userdata en utilisant lua_getmetatable
. Il extrait ensuite le nom de type donné du registre à l'aide de lua_getfield
et effectue un appel lua_rawequal
pour les comparer.
Vous pouvez toujours stocker un champ de marqueur dans la métatable avec une valeur de données utilisateur légère unique à votre module.
static const char *green_flavor = "green";
...
void my_setflavor(lua_State *L, void *flavor) {
lua_pushlightuserdata(L,flavor);
lua_pushlstring(L,"_flavor");
lua_rawset(L,-3);
}
void my_isflavor(lua_State *L, void *flavor) {
void *p = NULL;
lua_pushlstring(L,"_flavor");
lua_rawget(L,-2);
p = lua_touserdata(L,-1);
lua_pop(L,1);
return p == flavor;
}
Ensuite, vous pouvez utiliser my_setflavor(L,&green_flavor)
pour définir le champ de _flavor de la table en haut de la pile, et my_isflavor(L,&red_flavor)
pour tester le champ _flavor de la table en haut de la pile. Utilisé de cette façon, le champ _flavor ne peut prendre que les valeurs qui peuvent être créées par le code dans le module qui a le symbole green_flavor dans la portée, et rechercher le champ et tester sa valeur requiert uniquement une recherche de table en dehors de la récupération de la métatable elle-même. Notez que la valeur de la variable green_flavor n'a pas d'importance, puisque seule son adresse est réellement utilisée.
Avec plusieurs variables de saveur distinctes disponibles à utiliser comme valeurs sentinelles, le champ _flavor peut être utilisé pour distinguer plusieurs métatables associées.
Tout cela dit, une question naturelle est "pourquoi faire ceci du tout?" Après tout, le metatable pourrait facilement contenir toutes les informations dont il a besoin pour obtenir le comportement approprié. Il peut facilement contenir des fonctions ainsi que des données, et ces fonctions peuvent être récupérées et appelées depuis C et Lua.
La variable userdata doit avoir un metatable, donc saisissez-la; puis recherchez le nom que vous voulez dans le registre. Si les deux objets sont identiques, vous avez trouvé le type que vous recherchez.
Vous pouvez envoyer sur ce type en code C, mais permettez-moi de suggérer que vous désigniez un champ de la métatable à la place. Une fonction stockée dans la métatable devrait faire le travail, mais si ce n'est pas le cas, si vous devez absolument switch
en C, choisissez un nom, utilisez-le pour indexer dans la métatable, et assignez à chaque métatable un petit entier que vous pouvez activer.
meta1.decision = 1
meta2.decision = 2
meta3.decision = 3
puis dans votre code C
if (lua_getmetatable(L, 1)) {
lua_getfield(L, -1, "decision");
if (lua_isnumber(L, -1)) {
switch ((int) lua_tonumber(L, -1)) {
case 1: ... ; break;
case 2: ... ; break;
case 3: ... ; break;
}
return 0;
}
}
return luaL_error(L, "Userdata was not one of the expected types");
- 1. Liaisons Lua: table vs userdata
- 2. itération à travers une table Lua à partir de C++?
- 3. Comment coller le code Lua en C++?
- 4. Lua et C-struct
- 5. jqgrid userData publication null à l'actualisation
- 6. Comment faire des opérations de table lua à partir de C?
- 7. Comment passer une liste d'objets de C++ à Lua?
- 8. Comment charger et exécuter un fichier lua à partir d'un autre fichier lua
- 9. Comment inclure le langage de script lua dans C++ XCode?
- 10. Référence à la fonction Lua en C/C++
- 11. Exposition d'objets C# à l'écriture de scripts Lua
- 12. jax-ws: paramètre Content-Type de demande
- 13. Comment créer une table Lua en C++ et la passer à une fonction Lua?
- 14. C# Obtenir le nom du type dérivé à partir de la classe de base interne Classe
- 15. Résoudre le type CLR à partir de DataContract.Namespace?
- 16. Lua bindings à C++ et la collecte des ordures
- 17. Comment publier une demande SOAP à partir de .NET?
- 18. Const à double initialisés de Lua
- 19. .NET Type chargeable à partir de App.Config
- 20. Pouvez-vous exécuter le code C# à partir de C++?
- 21. C# HTTP Demande Parser
- 22. Motif Correspondance avec le module de chaîne de Lua
- 23. Lua "print" ne fonctionne pas en mode débogage à partir de Visual Studio
- 24. Demande de carte à puce
- 25. Inférence de type C# obtient le type incorrect
- 26. Concaténation de chaînes dans Lua
- 27. Obtenir le nom de domaine demandeur à partir de la demande WCF?
- 28. VB6 - Lua Integration
- 29. url ne décode pas correctement à la demande [] en C#
- 30. Incorporation: mono vs lua
Il semble que lua 5.2 ait ce que vous cherchez: [luaL_testudata] (http://www.lua.org/source/5.2/lauxlib.c.html#luaL_testudata) –