2017-08-03 2 views
1

Je fonction C++ (qui fonctionne une simulation physique dans mon moteur de jeu) qui ressemble à ceci:interace entre C++ et la fonction Lua avec des arguments de vecteur 3D

void doSomePhysics(int nIters, Vec3d pos, Vec3d vel){ /*... don't care ...*/ } 

Je veux appeler cette fonction à partir d'un script lua aime ça:

doSomePhysics(100, {1.0,-2.0,3.0}, {-8.0,7.0,-6.0}) 

J'essaie de comprendre comment faire l'interface Lua à cette fonction.

Je voudrais faire plusieurs fonctions générales d'assistance pour passer des vecteurs et des matrices 2D, 3D et 4D car je les utiliserai fortement.

Voici esquisse ce que je suis en train d'essayer de le faire (mais je sais que ce n'est pas correct):

void lua_getVec3(lua_State *L, Vec3d& vec){ 
    // universal helper function to get Vec3 function argument from Lua to C++ function 
    luaL_checktype(L, 1, LUA_TTABLE); 
    lua_settop(L, 1); 
    int a_size = lua_rawlen(L, 1); 
    lua_rawgeti(L, 1, 1); vec.x = lua_tonumber(L, -1); 
    lua_rawgeti(L, 2, 2); vec.y = lua_tonumber(L, -2); 
    lua_rawgeti(L, 3, 3); vec.z = lua_tonumber(L, -3); 
    lua_pop(L, 3); 
} 

int l_doSomePhysics(lua_State* L){ 
    // lua interface for doSomePhysics 
    Vec3d pos,vel; 
    int n = lua_tointeger(L, 1); 
    lua_getVec3(L, pos); 
    lua_getVec3(L, vel); 
    doSomePhysics(n,pos,vel); 
    lua_pushnumber(state, 123); 
    return 1; 
} 

J'ai lu plusieurs tutoriels courts 123 mais il semble horriblement compliqué, confus et sujettes aux erreurs ... Je suis complètement perdu dans les index de pile (quelle est ma position actuelle dans la pile ?, quel est l'index relatif correct? etc.). Je suis réticent à croire que le langage de script de jeux le plus célèbre nécessite tellement de code de plaque de chaudière et tant de douleur pour l'interfaçage de chaque petite fonction.


EDIT: Avec l'aide de Vlad j'ai pu le faire pour vecteur 3D et de la matrice

void lua_getVec3(lua_State *L, int idx, Vec3d& vec){ 
    // universal helper function to get Vec3 function argument from Lua to C++ function 
    luaL_checktype(L, idx, LUA_TTABLE); 
    lua_rawgeti(L, idx, 1); vec.x = lua_tonumber(L, -1); lua_pop(L, 1); 
    lua_rawgeti(L, idx, 2); vec.y = lua_tonumber(L, -1); lua_pop(L, 1); 
    lua_rawgeti(L, idx, 3); vec.z = lua_tonumber(L, -1); lua_pop(L, 1); 
} 

void lua_getMat3(lua_State *L, int idx, Mat3d& mat){ 
    // universal helper function to get Mat3 function argument from Lua to C++ function 
    luaL_checktype(L, idx, LUA_TTABLE); 
    lua_pushinteger(L, 1); lua_gettable(L, idx); lua_getVec3(L, -1, mat.a); lua_pop(L, 1); 
    lua_pushinteger(L, 2); lua_gettable(L, idx); lua_getVec3(L, -1, mat.b); lua_pop(L, 1); 
    lua_pushinteger(L, 3); lua_gettable(L, idx); lua_getVec3(L, -1, mat.c); lua_pop(L, 1); 
} 

extern "C" 
int l_doSomePhysics2(lua_State* L){ 
    // lua interface for doSomePhysics 
    Vec3d pos; 
    Mat3d mat; 
    int n = lua_tointeger(L, 1); 
    lua_getVec3(L, 2, pos); 
    lua_getMat3(L, 3, mat); 
    doSomePhysics2(n,pos,mat); 
    //lua_pushnumber(L, 123); 
    return 3; 
} 

œuvres pour cette fonction Lua:

mat = {{1.1,-0.1,0.1},{-0.2,2.2,0.2},{-0.3,0.3,3.3}} 
doSomePhysics2(100, {-7.7,8.8,9.9}, mat) 
+0

Une astuce lib est sol 2, solution d'en-tête unique et fait ce que vous voulez d'une manière plus facile. –

+0

Je le regardais déjà (avec dix autres bibliothèques de liaison lua). Mais utiliser une librairie ajoute toujours quelques problèmes (enfer de dépendance, exigence de C++ 14, temps de compilation plus long dû aux templates, distribution plus compliquée ...). Donc je préférerais vivre sans. –

Répondre

1

Votre void lua_getVec3(lua_State *L, Vec3d& vec) est manquante info vitale - emplacement de la table d'arguments sur une pile Lua. Réécrire à quelque chose comme:

void lua_getVec3(lua_State *L, int idx, Vec3d& vec){ 
    // universal helper function to get Vec3 function argument from Lua to C++ function 
    luaL_checktype(L, idx, LUA_TTABLE); 
    lua_rawgeti(L, idx, 1); vec.x = lua_tonumber(L, -1); 
    lua_rawgeti(L, idx, 2); vec.y = lua_tonumber(L, -1); 
    lua_rawgeti(L, idx, 3); vec.z = lua_tonumber(L, -1); 
    lua_pop(L, 3); 
} 

Et appelez comme:

int l_doSomePhysics(lua_State* L){ 
    // lua interface for doSomePhysics 
    Vec3d pos,vel; 
    int n = lua_tointeger(L, 1); 
    lua_getVec3(L, 2, pos); 
    lua_getVec3(L, 3, vel); 
    doSomePhysics(n,pos,vel); 
    lua_pushnumber(state, 123); 
    return 1; 
} 
+0

super ça marche. Il devrait aussi être 'return 3 ', n'est-ce pas? Y a-t-il quelque chose qui manque pour la sécurité, etc.? –

+0

hmm, désolé je n'ai pas appris beaucoup ... Je ne vois pas comment généraliser à la matrice '{{1.0, -0.1,0.1}, {- 0.2,2.0,0.2}, {- 0.3,0.3,3.0 }} ' –

+0

' return 3' sera nécessaire si vous renvoyez 3 valeurs de votre fonction. Jusqu'à présent, il ne s'agit que d'un seul nombre, donc «return 1». Matrix est juste une table de tables. 'lua_rawget()' les vecteurs individuels de cette table externe, récupèrent l'emplacement de la table du vecteur avec 'lua_gettop()', et appellent 'lua_getVec3()' comme précédemment. – Vlad