我遇到了这个人的问题: Lua userdata array access and methods
其中,当我设置我的用户数据元表的 __index 时,它总是调用 getter,而不是我没有为元事件声明的其他方法。上述链接的解决方案是在 Lua 中,我尝试了一个看起来不优雅的 C 实现,但无论如何,它会产生一个新问题,因为我的新方法不能再接受参数,并且我收到此错误:
attempt to call method 'asTable' (a table value)
在这个 Lua 声明中:
print_r(c:asTable() )
这就是我设置所有内容的方式:
//Methods, many of which are overridden Lua meta-events (with the underscores)
static const struct luaL_reg vallib_m [] = {
{"asTable", PushLuaTable}, //these functions are not called
{"asCopy", CopyLuaVal},
{"__newindex", SetLuaVal},
{"__index", GetLuaVal},
{"__tostring", ValToString},
{"__gc", GarbageCollectVal},
{"__metatable", HideMetaTable},
{NULL, NULL}
};
//Static library functions
static const struct luaL_reg vallib_f [] = {
{"specialprint", PrintVals},
{NULL, NULL}
};
int luaopen_custom(lua_State *L)
{
luaL_newmetatable(L, "custom.Value");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); /* pushes the metatable */
lua_settable(L, -3); /* metatable.__index = metatable */
luaL_register(L, NULL, vallib_m);
luaL_register(L, "special", vallib_f);
return 0;
}
然后在默认调用的getter(通过__index)中,我首先检查我打算调用的其他事件并将控制权转移给它们,如下所示。请注意,我从堆栈中删除了包含函数名称的参数。
//TODO: this is a tentative fix, I would rather do this with metatables
//checking for methods
if (lua_isstring(L, 2))
{
field = luaL_checkstring(L, 2);
if (unlikely(!field))
{
reporter->Warning("Fail in getter -- bad string as method attempt");
return LUA_FAILURE;
}
if (strcmp(field, "asTable") == 0)
{
lua_remove(L, 2); //delete string "asTable"
return PushLuaTable(L);
}
else if (strcmp(field, "asCopy") == 0)
{
lua_remove(L, 2); //delete string "asCopy"
return CopyLuaVal(L);
}
//... other methods.
else
{
//Insert string back into stack??
}
}
无论传递了多少参数,它都不会将我的方法视为函数,并且即使有任何括号或冒号也会引发错误。(它可以通过 来访问c.asTable
,这对于不带参数的方法工作得很好,但我计划添加一些这样做的方法,无论如何,语法与方法不一致。
在任何情况下,最好不要通过我的 C getter 调用这些函数,而是使用元表来解决这个问题。如果可能,请提供一个使用 C API 的示例——Lua 中已经有 StackOverflow 解决方案,但我无法将它们翻译成 C。