【问题标题】:Referencing metatable Created in C from Lua 5.1.5引用从 Lua 5.1.5 用 C 语言创建的元表
【发布时间】:2013-05-17 04:34:05
【问题描述】:

在我的 C 中,我创建了一个全局元表:

luaL_newmetatable(L, "WebSocketClient");
lua_pushliteral(L, "close");
lua_pushcfunction(L, lws_sock_close);
lua_rawset(L, -3);
lua_pop(L, 1);

但在我的 Lua 中,我无法为其添加函数:

function WebSocketClient:read_frame()
   --foo
end

我收到此错误:

attempt to index local 'WebSocketClient' (a nil value)

如何使这个元表可用于我的 Lua 代码,以便向它添加更多功能?

【问题讨论】:

  • 在 Lua 中元表的处理方式不同。您通常希望创建一个带有函数的普通表,然后将其传递给 setmetatable 函数,该函数应该对其进行转换。看here。 WRT luaL_newmetatable, this short doc 可能会有所帮助。
  • 我是凭记忆输入版本的,但我错了,我用的是5.1.5。

标签: lua


【解决方案1】:

扩展 Bartek 的评论(这是正确的,虽然简短):如果您想从 Lua 向元表添加新功能,则需要将该表公开给 Lua。 luaL_newmetatable 将您的 WebSocketClient 元表存储在 Registry 中,只能通过 C 访问(在调试 API 中的 debug.getregistry 之外,在对 Lua 代码进行沙箱处理时可能会删除它)。

你最好创建一个普通表,通过你的 C 库的表导出它,然后使用luaL_setmetatable(来自 C)或 setmetatable(来自 Lua)——将注册表视为一个放置内部值的地方到 C 模块。

您使用 luaL_newmetatable 的方式定义了一个元表,出于安全原因,该元表明确不应从 Lua 访问,例如Lua 脚本最终用户不能弄乱核心类型的元表。在其他情况下很有用,但不是你想要的。

【讨论】:

  • 我当时有点忙,不想贴这么不完整的提示作为答案,所以决定发表评论。 +1,说得好。
【解决方案2】:

根据@silentbicycle 的回答提供代码:

lua_newtable(L);
lua_pushliteral(L, "close");
lua_pushcfunction(L, lws_sock_close);
lua_rawset(L, -3);
lua_setglobal(L, "WebSocketClient");

作为参考,您可以像这样设置元表:

lua_newtable(L);
lua_newtable(L);
lua_pushliteral(L, "__index");
lua_getglobal(L, "WebSocketClient");
lua_settable(L, -3);
lua_setmetatable(L, -2);
lua_settable(L, -3);

【讨论】:

  • 使用lua_setglobal 代替lua_setfield(L, LUA_GLOBALSINDEXlua_getglobal 代替lua_getfield(L, LUA_GLOBALSINDEX
  • @lhf 这些只是宏,不是吗?啊哈! #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))getglobal 是类比的。
  • @BartekBanachewicz,是的,它们是 5.1 中的宏,但在 5.2 中起作用。使用它们使代码在两个版本中都可以工作。
猜你喜欢
  • 1970-01-01
  • 2011-02-25
  • 2016-04-29
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
相关资源
最近更新 更多