Lua C Extension: how to set metatable on new library
经过多次尝试和数小时的谷歌搜索,我终于意识到 SOF 可能是我解决这个问题的最佳场所。
我目前正在使用 Lua C API 创建一个扩展,这是一个共享库,您可以通过 require 要求它来使用它。我正在尝试做与此非常相似的事情(对格式感到抱歉):
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
local data = {
something =“some” } local rpc = {} function rpc.method() function rpc.method2() local metatable = {} |
我当前的 C 代码如下所示:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
static int lua_index(lua_State* lua) { //idk
std::cout <<“Was indexed”; const char* a = luaL_checkstring(lua, 2); std::cout << a << std::endl; return 0; } static int lua_initialize(lua_State* lua) { static const struct luaL_Reg lib[] = { extern“C” int DISCORD_RPC_EXPORT luaopen_DiscordRPC(lua_State* lua) { return 1; |
并以此为例:
1
2 3 4 5 |
local rpc = require“DiscordRPC”
print(rpc[‘a’]) rpc.initialize(); |
现在显然 rpc[‘a’] 会返回 nil(是的,lua_index 实际上会运行),因为 lua_index 什么也没做,但为什么我不能调用 initialize?它显然在那里。它说: lua: main.lua:5: attempt to call a nil value (field ‘initialize’) 所以它是零。如果我要删除 lua_setmetatable(lua, 1); 我将能够调用该函数,但我不能像我想要的那样索引它 DiscordRPC 。另外我想指出,当我删除它时,__index 元方法会被调用两次,显然它会。
我的问题:我怎样才能做到这一点?我正在尝试在表上设置一个元表并返回整个元表。
非常感谢任何帮助,因为我完全迷路了。谢谢。
- 这个问题似乎与 c 无关。
- 代码编译为 C,我确实使用了一些 C 头文件以及 extern C。我想我也可以添加它。
您必须通过将元表推到堆栈顶部然后调用 lua_setmetatable.
来将元表设置到您的表中
1
2 3 |
luaL_newlib(lua, lib);
lua_pushvalue(lua, –1); lua_setmetatable(lua, –2); |
对 lua_pushvalue 的调用会将位置 -1(堆栈顶部)的值再次推送到堆栈,并复制它。然后,我们调用 lua_setmetatable(Documentation here doc) 在堆栈顶部弹出一个表,并将其设置为给定索引中表的元表(-2,即我们的库,由 luaL_newlib 命令推送).
通过这样做并运行您的示例,我得到了以下结果:
1
2 3 4 5 6 7 |
local rpc = require“DiscordRPC”
print(rpc[‘a’]) — First, calls the __index function, printing — ‘Was indexeda’ — Then prints nil, since the key ‘a’ holds nothing rpc.initialize(); — Prints ran |
如果你对此有更多疑问,我建议你阅读 Lua Book 中关于用户数据和面向对象访问的章节。
来源:https://www.codenong.com/50845264/