Ho una classe in C++ chiamato "Punto":Come estrarre C++ puntatore oggetto da Lua
class Point
{
public:
int x, y;
//constructor
Point(int x, int y)
{
this->x = x;
this->y = y;
}
};
Il mio obiettivo è quello di essere in grado di istanziare un oggetto Point con uno script Lua, ed estrarre il puntatore questo oggetto dalla pila Lua.
Ecco il mio (attualmente non funzionante) tentativo che si spera chiarisca cosa esattamente sto cercando di fare; notare che questo codice è essenzialmente modificato copia/incolla da this tutorial e che sto usando Lua 5.2:
static int newPoint(lua_State *L)
{
int n = lua_gettop(L);
if (n != 2)
return luaL_error(L, "expected 2 args for Point.new()", n);
// Allocate memory for a pointer to object
Point **p = (Point **)lua_newuserdata(L, sizeof(Point *));
double x = luaL_checknumber (L, 1);
double y = luaL_checknumber (L, 2);
//I want to access this pointer in C++ outside this function
*p = new Point(x, y);
luaL_getmetatable(L, "Point"); // Use global table 'Point' as metatable
lua_setmetatable(L, -2);
return 1;
}
static const luaL_Reg pointFuncs[] = {
{"new", newPoint},
{NULL, NULL}
};
//register Point to Lua
void registerPoint(lua_State *L)
{
lua_createtable(L, 0, 0);
// Register metatable for user data in registry
luaL_newmetatable(L, "Point");
luaL_setfuncs(L, pointFuncs, 0);
lua_pushvalue(L,-1);
lua_setfield(L,-2, "__index");
lua_setglobal(L, "Point");
}
Point* checkPoint(lua_State* L, int index)
{
void* ud = 0;
luaL_checktype(L, index, LUA_TTABLE);
lua_getfield(L, index, "__index");
ud = luaL_checkudata(L, index, "Point");;
return *((Point**)ud);
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
registerPoint(L);
luaL_dofile(L, "testz.lua");
lua_getglobal(L, "Point");
Point *foo = checkPoint(L, lua_gettop(L));
std::cout << "x: " << foo->x << " y: " << foo->y;
lua_close(L);
return 0;
}
E qui è lo script Lua:
local point = Point.new(10,20)
L'esecuzione di questo codice, ottengo il seguente errore : "argomento non valido # 3 (punto previsto, ottenuto tabella)" alla riga: ud = luaL_checkudata (L, indice, "Punto") all'interno della funzione checkPoint().
Se qualcuno potesse guidarmi nella giusta direzione, sarebbe molto apprezzato.
Esattamente quello che dovevo sapere! 1000 volte grazie a voi signore. – user2687268
@ user2687268 Ho aggiunto una nota sulla gestione di userdata clean. – greatwolf
questa è una buona spiegazione, ma sembra presumere che il garbage collector non verrà eseguito prima che il puntatore del punto ottenga il punto dallo stato lua. Questo potrebbe non essere il caso con questo semplice esempio, ma in script più elaborati non saprai quando gc cancellerà il tuo punto. Quindi, tutta la confusione della gestione della memoria nella vita delle librerie vincolanti. –