如何修改由C API创建的元表?

时间:2019-03-25 13:05:43

标签: lua

我想向由C API创建的lua对象添加一些方法或属性。我无法以常规方式添加属性,例如:

local foo = libc.new()
foo.bar = "hello"

说:

  

无法运行脚本:尝试索引libc_meta值(本地'foo')

所以我认为可能需要修改metatable,所以我更改了代码:

local foo = libc.new()
local mt = getmetatable(foo)
foo[bar] = "hello"
setmetable(foo, mt)

不幸的是,它仍然无法正常工作。

  

无法运行脚本:“ setmetatable”的参数#1错误(应该是表,得到了libc_meta)

那么我如何向该'foo'添加方法或属性?

顺便说一句,C代码在这里:

static int libc_new(lua_State *L) {
    ...
    lua_lib_space *libc = lua_newuserdata(L, sizeof(*libc));
    libc->L = L;
    libc->cb_enter = cb_enter;
    libc->cb_leave = cb_leave;
    luaL_getmetatable(L, "libc_meta");
    lua_setmetatable(L, -2);
    lib_space *lib = lib_new(enter, leave, libc);
    libc->space = lib;
    return 1;
}

1 个答案:

答案 0 :(得分:2)

用户数据应由C创建,由C代码操纵,并且仅用于C代码预期的目的。 Lua可以和它交谈,但是只能用C允许的方式交谈。这样,尽管userdata可以具有一个元表(并且这些元方法是Lua可以“直接”与userdata进行交互的 only 方法),但是只有C函数(和debug库,但这是作弊)可以直接操纵该元表。 Lua是一种嵌入式语言,而C具有首要地位。如果某个C库想将您拒之门外,那就可以。

您可以 要做的是获取用户数据并将其粘贴到您自己的表中,然后为该表提供一个元表。在您的__index元方法中,如果您有特定键的替代或新方法,则将访问权限转发给该键。否则,它将只访问存储的用户数据。

但是,如果您从userdata中获得的是一个函数,则可能有问题。可见,大多数userdata函数将userdata作为参数。实际上,大多数都是通过“ ud:func_name(params). But if that ud`进行调用的,实际上它是表包装器,然后传递给该函数的第一个参数将是 wrapper ,而不是用户数据本身。

这带来了一个问题。当从用户数据中获得的东西是一个函数时,您需要为该函数返回一个包装器,该包装器将遍历参数并将对包装器表的所有引用转换为实际的用户数据。