【发布时间】:2015-01-14 05:23:39
【问题描述】:
我正在用 C 语言编写一个用于 Lua 的用户数据类型。它还有一些数组类型的属性和各种方法。现在如果你是这种类型,我使用u:set(k,v) resp。 u:get(k) 访问数据,例如u:sort() 作为方法。为此,我将__index 设置为包含这些方法的表。现在,如果我想使用u[k] = v 或u[k] 访问数据,我需要将__newindex 和__index 设置为set 和get。但随后其他方法不再可用......
在 C 中处理这个问题的最佳方法是什么?我猜我需要用 C 编写一个函数来注册为__index 并以某种方式在那里处理它。也许检查 key 是否属于 Lua 方法表,如果是,则调用它。
任何帮助/提示将不胜感激。我没有找到这样的例子,尽管(对我来说)这似乎是一件很自然的事情。
编辑:在 Lua 中添加了我的 C 版本解决方案,发布在下面的答案中。这或多或少是直接翻译,所以所有功劳都归于@gilles-gregoire。
以下 C 函数注册为 __index 元方法。
static int permL_index(lua_State *L) {
struct perm **pp = luaL_checkudata(L, 1, PERM_MT);
int i;
luaL_getmetatable(L, PERM_MT);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if ( lua_isnil(L, -1) ) {
/* found no method, so get value from userdata. */
i = luaL_checkint(L, 2);
luaL_argcheck(L, 1 <= i && i <= (*pp)->n, 2, "index out of range");
lua_pushinteger(L, (*pp)->v[i-1]);
};
return 1;
};
这是执行此操作的代码,
int luaopen_perm(lua_State *L) {
luaL_newmetatable(L, PERM_MT);
luaL_setfuncs(L, permL_methods, 0);
luaL_setfuncs(L, permL_functions, 0);
lua_pop(L, 1);
luaL_newlib(L, permL_functions);
return 1;
};
permL_methods 在哪里
static const struct luaL_Reg permL_methods[] = {
{ "__index", permL_index },
{ "__eq", permL_equal },
{ "__tostring", permL_tostring },
{ "__gc", permL_destroy },
[...]
{ NULL, NULL }
};
而permL_functions 是
static const struct luaL_Reg permL_functions[] = {
{ "inverse", permL_new_inverse },
{ "product", permL_new_product },
{ "composition", permL_new_composition },
[...]
{ NULL, NULL }
};
【问题讨论】:
-
这对我来说似乎是一个合理的方法。
-
Programming in Lua 有一个详尽的教程,用于在 C 中创建数组类型,其中包括在 C 中添加元方法。它是由 Lua 的一位设计者编写的,可免费获得。
-
谢谢@rpattiso,我知道。但是,它不能解决我的问题 AFAICT。
-
你确定吗? this page 将
__index和__newindex方法添加到用户定义的 C 数组类型。他们将这些添加为a:get(10)和a:set(10, 3.4)的第二个选项,因此它将与a[10]和a[10]=3.4相同。我从你的问题中不明白什么? -
@rpattiso:它们用
__index和__newindex表示法替换了get()和set()方法。在他们完成此操作后,a:get(10)会产生mt.__index(a,"get")(10)。我想要两种方法(如a:sort())和索引符号。
标签: c lua lua-api lua-userdata