Lua userdata: 无法同时访问数组和方法

我遇到了这个问题: Lua userdata array access and methods

在我设置userdata的metatable后,无论我是否为元事件声明了其他方法,它总是调用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调用这些函数,而是使用metatable解决此问题。如果可能的话,请使用C API提供一个示例--已经存在Lua的StackOverflow解决方案,但我无法将它们翻译为C。

点赞