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

问题描述 投票:1回答:1

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

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)

不幸的是,它仍然无效。

无法运行脚本:错误的参数#1到'setmetatable'(表预期,得到了libc_meta)

那么如何为这个'foo'添加方法或属性呢?

BTW,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个回答
2
投票

Userdata意味着由C创建,由C代码操纵,并且仅用于C代码的目的。 Lua可以与它交谈,但只能以C允许的方式进行。因此,虽然userdata可以有metatable(并且那些metame方法是Lua可以“直接”与userdata交互的唯一方式),但只有C函数(和debug库,但那是作弊)可以直接操作该metatable。 Lua是一种嵌入式语言,C具有首要地位;如果某个C库想让你闭嘴,它可以。

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

但是,如果您在userdata中获得的是一个函数,那么您可能会遇到问题。请参阅,大多数userdata函数将userdata作为参数;实际上,大多数意味着通过“ud:func_name(params). But if thatud`调用实际上是表包装器,然后传递给函数的第一个参数将是包装器,而不是userdata本身。

这造成了一个问题。当你从userdata得到的东西是一个函数时,你需要为该函数返回一个包装器,它通过参数并将对包装器表的任何引用转换为实际的用户数据。

© www.soinside.com 2019 - 2024. All rights reserved.