经过多次尝试和数小时的谷歌搜索,我终于意识到,软件可能是我解决这个问题的最佳场所。
我目前正在使用Lua C API创建一个扩展,这是一个共享库,您可以通过require要求它使用它。我正在尝试执行与此非常类似的操作(对格式设置感到抱歉):

local data = {
    something = "some"
}

local rpc = {}

function rpc.method()
    print('ran')
 end

 function rpc.method2()
    print('ran222')
  end

   local metatable = {}
   metatable.__index = function(self, key)
       return data[key]
    end
   setmetatable(rpc, metatable)
--------------------------------------------
rpc.method()
print(rpc['something'])
rpc.method2()

我当前的C代码如下所示:
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) {
    std::cout << "ran";
    return 0;
}

static const struct luaL_Reg lib[] = {
    { "initialize", lua_initialize },
    {"__index", lua_index},
    { NULL, NULL }
};

extern "C" int DISCORD_RPC_EXPORT luaopen_DiscordRPC(lua_State* lua) {
    luaL_newlib(lua, lib);
    lua_setmetatable(lua, 1);

    return 1;
}

并以此为例:
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元方法会被调用两次,显然它会。
我的问题是:我怎样才能做到这一点?我试图在一个表上设置一个元表并返回整个元表。
非常感谢您的帮助,因为我完全迷路了。谢谢您。

最佳答案

必须将元表推到堆栈的顶部,然后调用lua_setmetatable,才能将其设置为表。

luaL_newlib(lua, lib);
lua_pushvalue(lua, -1);
lua_setmetatable(lua, -2);

lua_pushvalue的调用将再次将位置-1(堆栈顶部)上的值推送到堆栈,并复制它。然后,我们调用lua_setmetatable(这里的文档doc)在堆栈顶部弹出一个表,并将其设置为给定索引中表的元表(-2,即lib,由luaL_newlib命令推送)。
通过这样做并运行您的示例,我得到了以下结果:
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书籍中关于Userdata and Object-Oriented Access编程的章节。

关于c - Lua C扩展:如何在新库上设置元表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50845264/

10-11 15:32