How to register C++ nested class to Lua
目前,我能够将C ++类绑定到Lua,并包装在使用
但是,如果我想绑定一个嵌套的类怎么办?
考虑以下C ++代码:
1 2 3 4 5 6 7 8 9 10 11 | class Foo { public: Foo(){} void do_something(); class Bar { public: Bar(){} void do_something_else(); }; }; |
和Lua注册:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | int foo_new(lua_State* L) { new(lua_newuserdata(L, sizeof(foo)))foo(); luaL_setmetatable(L,"Foo"); return 1; } int foo_do_something(lua_State* L) { Foo* foo = (Foo*)luaL_checkudata(L, 1,"Foo"); foo->do_something(); return 0; } int luaopen_foo(lua_State* L) { const luaL_Reg functions[] = { {"__index", foo_new}, {"do_something", foo_do_something}, {nullptr, nullptr} }; if( luaL_newmetatable(L,"Foo") ) { luaL_setfuncs(L, functions, 0); lua_pushvalue(L, -1); lua_setfield(L, -2,"__index"); } return 1; } ... luaL_requiref(L,"Foo", luaopen_foo, 1); |
我可以这样在Lua中访问
1 2 | foo = Foo() foo:do_something() |
现在的问题是:如何在Lua中注册
1 2 | bar = Foo.Bar() bar:do_something_else() |
本质上,我想在
谢谢!
编辑:好的,现在是一个完全不同的问题。
是的,您可以在一个电话中完成。
我假设您不想将
因此,只需将其作为
附言确保曾经调用过析构函数:通常,如果将
EDIT2:修改luaopen_Foo方法(对于构造函数,请注意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | int luaopen_foo(lua_State* L) { static const luaL_Reg functions[] = { {"__call" , foo_new}, {"do_something" , foo_do_something}, {nullptr , nullptr} }; if (luaL_newmetatable(L,"Foo")) { luaL_setfuncs(L, functions, 0); lua_pushvalue(L, -1); lua_setfield(L, -2,"__index"); // ================= // Here, your"Foo" metatable is on top of your stack // about to be returned as the result of your luaopen_Foo. // Simply put another table above and set if as a Foo.Bar if (luaopen_FooBar(L)) lua_setfield(L, -2,"Bar"); } return 1; } int luaopen_FooBar(lua_State * L) { static const luaL_Reg functions[] = { {"__call" , foo_bar_new}, {"do_something_else" , foo_bar_do_something_else}, {nullptr , nullptr} }; // luaL_newmetatable puts its result on top of the stack // - exactly what we want for lua_setfield if (luaL_newmetatable(L,"Foo::Bar")) { luaL_setfuncs(L, functions, 0); lua_pushvalue(L, -1); lua_setfield(L, -2,"__index"); } return 1; // Indicate the result is on top of the stack } |
如果您感到好奇,那么luaL_requiref函数(带有一些伪代码)是什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void luaL_requiref(lua_State *L, const char *name, lua_CFunction openf, int set_global) { if (!try_get_already_loaded_module(modname)) { lua_pushcfunction(L, openf); // Call the openf function lua_pushstring(L, modname); // with modname as its argument lua_call(L, 1, 1); memorize_the_result_for_future(modname); } if (set_global) { lua_pushvalue(L, -1); // copy the module lua_setglobal(L, modname); // set _G[modname] = module } } |
请注意不同之处: