【问题标题】:How to return C++ object to lua 5.2?如何将 C++ 对象返回到 lua 5.2?
【发布时间】:2013-01-15 02:16:58
【问题描述】:

如何将 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 测试如下:

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 元表如下

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 绑定框架,我使用的是纯 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 显示元表是正确的。

userdata
  say     function: 00602860
  new     function: 00493665

但是 lua 中仍然显示同样的错误

b:say()   <-- attempt to index local 'b' (a userdata value)

=== 更新 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)

=== 更新 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

【问题讨论】:

  • 我认为你还需要设置它的元表来定义它的方法。
  • luaL_newmetatable(l, "MyClass");
  • 什么是methods?此外,您的 a 不应该工作;你在使用一些 Lua 绑定框架将MyClass 绑定到 Lua 吗?
  • 如果你想像在 lua 对象上一样操作它,userdata 将不起作用。
  • Wali~如果你没有userdata那用什么?

标签: c++ lua lua-5.2


【解决方案1】:

您没有将您从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 函数,然后它应该转换、取消引用和删除数据。

【讨论】:

  • @Flash 哎呀,试试luaL_getmetatable(l, "MyClass") 而不是lua_getglobal
  • @Flash 你确定你注册的功能正确吗?我在 l_registerClass 中没有看到你实际上给 say 一个名字的地方。
  • 试试 luaL_setmetatable 替换 luaL_getmetatable+ lua_setmetatable
  • 如果我没有正确注册。我的 lua 显示元表将为零。
【解决方案2】:

感谢 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 测试代码运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 2021-07-15
    • 2018-07-18
    • 2023-03-27
    • 2021-12-27
    • 2016-07-05
    相关资源
    最近更新 更多