How to extract C++ object pointer from Lua -
i have class in c++ called "point":
class point { public: int x, y; //constructor point(int x, int y) { this->x = x; this->y = y; } };
my goal able instantiate point object lua script, , extract pointer object lua stack.
here (currently not working) attempt clarifies trying do; note code modified copy/paste this tutorial , using lua 5.2:
static int newpoint(lua_state *l) { int n = lua_gettop(l); if (n != 2) return lual_error(l, "expected 2 args point.new()", n); // allocate memory pointer object point **p = (point **)lua_newuserdata(l, sizeof(point *)); double x = lual_checknumber (l, 1); double y = lual_checknumber (l, 2); //i want access pointer in c++ outside function *p = new point(x, y); lual_getmetatable(l, "point"); // use global table 'point' metatable lua_setmetatable(l, -2); return 1; } static const lual_reg pointfuncs[] = { {"new", newpoint}, {null, null} }; //register point lua void registerpoint(lua_state *l) { lua_createtable(l, 0, 0); // register metatable 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; }
and here lua script:
local point = point.new(10,20)
running code, following error: "bad argument #3 (point expected, got table)" @ line: ud = lual_checkudata(l, index, "point") inside checkpoint() function.
if 1 steer me in right direction, appreciated.
there couple of issues in above usage , binding.
inside testing script, local point
will not seen host c++ program. because, well, it's local script. if want accessible c++, either return point
value script or make global , retrieve using lua_getglobal(l, "point")
.
the checkpoint
function has unnecessary code. if @ other lual_check*
functions provided lua c api, check if given value @ stack index right type. if convert type on c++ can use.
so in 'checkpoint' function need is:
point* checkpoint(lua_state* l, int index) { return *((point **) lual_checkudata(l, index, "point")); }
if change script this, example:
local point = point.new(10,20) return point
you should able access point
c++ in following way:
// ... lual_dofile(l, "testz.lua"); point *foo = checkpoint(l, -1); std::cout << "x: " << foo->x << " y: " << foo->y; // ...
another important point regarding c++ object lifetime when exposed lua. because you're allocating , constructing c++ 'new' operator whenever point.new
called script, indirectly saying let lua handle exposed c++ object's lifetime. means you'll want implement __gc
metamethod act 'finalizer' or non-deterministic destructor. without have no way 'delete' point
object , reclaim space when lua garbage collects corresponding userdata.
to can augment code follows:
write
deletepoint
function gets called lua on userdata gc.static int deletepoint(lua_state *l) { pointer **p = checkpoint(l, 1); delete *p; *p = null; // not needed safe return 0; }
add
pointfuncs
lua knows it.static const lual_reg pointfuncs[] = { {"new", newpoint}, {"__gc", deletepoint}, {null, null} };
Comments
Post a Comment