【问题标题】:How to modify a metatable which was created by C API?如何修改由 C API 创建的元表?
【发布时间】:2019-03-25 13:05:42
【问题描述】:

我想向 lua 对象添加一些方法或属性,因为元数据是由 C API 创建的。我无法以正常方式添加属性,例如:

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

它说:

运行脚本失败:尝试索引 libc_meta 值(本地“foo”)

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

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;
}

【问题讨论】:

    标签: lua


    【解决方案1】:

    用户数据旨在由 C 创建,由 C 代码操作,并且仅用于 C 代码预期的目的。 Lua 可以与它​​对话,但只能以 C 允许的方式。因此,虽然 userdata 可以有一个元表(这些元方法是 Lua 可以“直接”与 userdata 交互的唯一方式),但只有 C 函数(和 debug 库,但那是作弊)可以直接操作那个元表。 Lua 是嵌入式语言,C 居首位;如果某个 C 库想把你拒之门外,它可以。

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

    但是,如果您在 userdata 中获得的是一个函数,那么您可能会遇到问题。看,大多数 userdata 函数都以 userdata 作为参数;实际上,大多数是通过“ud:func_name(params). But if thatud` 调用的,实际上是表包装器,那么传递给函数的第一个参数将是包装器,而不是用户数据自己。

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

    【讨论】:

    • 请注意:“只有 C 函数可以直接获取该可熔体”。 C 可以做到这一点,但它不是默认值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 2023-03-19
    • 2019-08-18
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    相关资源
    最近更新 更多