如何将C ++对象返回到lua?
我的C ++代码如下:
class MyClass
{
public:
void say()
{
print("Hello\r\n");
}
};
int test(lua_State* l)
{
MyClass* obj = new MyClass();
lua_pushlightuserdata(l, obj);
return 1;
}
Lua Test正在关注:
local a = MyClass:new()
a:say() <--- OK, beacause I set metatable!!
local b = test()
b:say() <--- ERROR: attempt to index local 'b' (a userdata value)
如何修改test()函数才能正常工作?
obj将由lua自动毁灭?
PS:我已经设置了MyClass metatable跟随
void l_registerClass()
{
lua_newtable(l);
int methods = lua_gettop(l);
luaL_newmetatable(l, "MyClass");
int metatable = lua_gettop(l);
lua_pushvalue(l, methods);
lua_setglobal(l, "MyClass");
lua_pushvalue(l, methods);
l_set(l, metatable, "__metatable");
//set metatable __index
lua_pushvalue(l, methods);
l_set(l, metatable, "__index");
//set metatable __gc
lua_pushcfunction(l, l_destructor);
l_set(l, metatable, "__gc");
//set method table
lua_newtable(l); // mt for method table
lua_pushcfunction(l, l_constructor);
lua_pushvalue(l, -1); // dup new_T function
l_set(l, methods, "new"); // add new_T to method table
l_set(l, -3, "__call"); // mt.__call = new_T
lua_setmetatable(l, methods);
// set methods metatable
lua_pushstring(l, "say");
lua_pushcclosure(l, l_proxy, 1);
lua_settable(l, methods);
lua_pop(l, 2);
}
int l_proxy(lua_State* l)
{
int i = (int)lua_tonumber(l, lua_upvalueindex(1));
lua_remove(l, 1); // remove self so member function args start at index 1
//call real function
MyClass* obj = getInstance();
obj->say();
return 1;
}
我不应该失去一步吗?
我没有使用任何Lua Binding Framework,我使用的是纯Lua库。
====更新1 ====
感谢user1520427的回答,但....
int test(lua_State* l)
{
MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
*c = new MyClass(); // we manage this
lua_getglobal(l, "MyClass");
lua_setmetatable(l, -2);
return 1;
}
我在Lua中测试它
local b = test()
print( type(b) )
local meta = getmetatable(b)
for k,v in pairs(meta) do
print(" ", k, v)
end
Lua show metatable是正确的。
userdata
say function: 00602860
new function: 00493665
但是lua仍然在
中显示相同的错误b:say() <-- attempt to index local 'b' (a userdata value)
=== update 2 ===
int test(lua_State* l)
{
MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
*c = new MyClass(); // we manage this
luaL_getmetatable(l, "MyClass"); //
lua_getglobal(l, "MyClass");
lua_setmetatable(l, -2);
return 1;
}
lua测试结果:
b:say() <-- attempt to call method 'say' (a nil value)
=== update 3 ===
int test(lua_State* l)
{
MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
*c = new MyClass(); // we manage this
luaL_getmetatable(l, "MyClass");
luaL_setmetatable(l, "MyClass"); //modify
return 1;
}
Lua测试结果:
b:say() <-- calling 'say' on bad self
答案 0 :(得分:2)
您没有将从test
返回的内容与您注册的课程相关联。尝试类似:
int test(lua_state* l) {
MyClass** c = lua_newuserdata(l, sizeof(MyClass*)); // lua will manage the MyClass** ptr
*c = new MyClass(); // we manage this
luaL_getmetatable(l, "MyClass");
lua_setmetatable(l, -2);
return 1;
}
这是我的头脑,但你明白了。你已经设置了析构函数,所以当Lua垃圾收集用户数据时,它会调用你的__gc
func,然后应该转换,取消引用和删除数据。
答案 1 :(得分:0)
感谢user1520427和lhf
正确的代码如下:
int test(lua_State* l)
{
MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
*c = new MyClass(); // we manage this
luaL_setmetatable(l, "MyClass"); //assign MyClass metatable
return 1;
}
Lua测试代码工作正常。