【问题标题】:Lua C Extension: how to set metatable on new libraryLua C 扩展:如何在新库上设置元表
【发布时间】:2018-11-23 12:14:14
【问题描述】:

经过多次尝试和数小时的谷歌搜索,我终于意识到 SOF 可能是我解决这个问题的最佳场所。

我目前正在使用 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。另外我想指出,当我删除它时,__index 元方法会被调用两次,显然会。

我的问题:我怎样才能做到这一点?我正在尝试在表上设置一个元表并返回整个元表。 非常感谢任何帮助,因为我完全迷路了。谢谢。

【问题讨论】:

  • 这个问题好像和c++没什么关系。
  • 代码编译为 C++,我确实使用了一些 C++ 头文件以及extern C。我想我不妨添加它。

标签: c lua


【解决方案1】:

您必须通过将元表推到堆栈顶部然后调用lua_setmetatable 来将元表设置到您的表中。

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

lua_pushvalue 的调用会将位置-1(堆栈顶部)的值再次压入堆栈,并复制它。然后,我们调用lua_setmetatable(此处的文档doc)在堆栈顶部弹出一个表并将其设置为给定索引中表的元表(-2,即我们的库,由@987654327推送@ 命令)。

通过这样做并运行您的示例,我得到了以下结果:

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 的章节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-13
    • 1970-01-01
    • 2018-09-12
    • 2017-02-01
    • 2015-12-20
    • 2022-01-11
    • 2015-07-31
    • 2020-12-09
    相关资源
    最近更新 更多