我正在用 C 语言编写用于 Lua 的用户数据类型。它还有一些数组类型的属性和各种方法。现在,如果你属于这种类型,我会使用u:set(k,v)
resp。u:get(k)
访问数据,例如u:sort()
作为方法。为此,我设置__index
了一个包含这些方法的表。现在,如果我想使用u[k] = v
or访问数据u[k]
,我需要设置__newindex
和resp 。但随后其他方法不再可用......__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 }
};