luaL_checkudata 继承性检查

我有以下场景:

一个名为“Base”的类和第二个名为“Derived”的类,它从“Base”派生。我使用元表在Lua中支持继承。然而,我需要一个解决方案,用于检查是否从指定类继承了传递的用户数据。

static int BaseGetMyVar(lua_State *state)
{
    Base* base = *(Base**)luaL_checkudata(state, 1, "Base");
    //Base* base = *(Base**)lua_touserdata(state, 1);
    lua_pushinteger(state, base->GetMyVar());
    return 1;
}

当我将“Derived” udata传递到此方法时,我会得到:

HelloWorld.lua:17: calling 'getMyVar' on bad self (Base expected, got userd
ata)

如何检查继承关系?这样我就可以传递Base或Derived。

当前我找到的解决方案:

http://lua-users.org/lists/lua-l/2005-06/msg00000.html

http://lua-users.org/lists/lua-l/2007-04/msg00324.html

https://github.com/diegonehab/luasocket/blob/master/src/auxiliar.c

siffiejoe的提案(感谢)

https://github.com/siffiejoe/lua-moon#moon_defcast

无意中发现的另一种解决方案:

http://lua-users.org/lists/lua-l/2013-06/msg00492.html

我的解决方案(我喜欢拥有自己的东西)

void* luaL_checkclass(lua_State *L, const char *classname, int objidx)
{
    if(!luaL_getmetafield(L, objidx, "__index"))
        return NULL;
    lua_getfield(L, -1, "__name");
    if(lua_type(L, -1) != LUA_TSTRING)
        return NULL;
    char const* basename = lua_tostring(L, -1);
    lua_pop(L, 2);
    if(strcmp(basename, classname) != 0)
        luaL_typeerror(L, objidx, classname);
    return lua_touserdata(L, objidx);
}

我想出了自己的想法。这需要元表具有 __name 字段(Lua 5.3实现了这个,但你仍然可以在之前的版本中自己添加此字段)。

更详细:

我在Lua中注册的每个元表都拥有 __index 字段,该字段被分配给self或者如果它有一个基类,则被分配给基类。在 __index 表中拥有 __name 字段,该字段是类的名称...我们可以比较这些名称。

如果我们现在将Derived对象传递到Base方法中,它将正常工作。

点赞
用户3586583
用户3586583

一个我觉得简单的方法是让表格看起来像这样:

Base = {Base = true}
Base.__index = Base
Derived = setmetatable({Derived = true}, Base)
Derived.__index = Derived

obj = setmetatable({}, Derived)

现在,检查 obj 是否继承 Base 很简单。只需执行 obj.Base,如果 Base 被继承,则返回 true。在 C 语言中,您可以使用 lua_setfieldlua_getfield 方法从元表中设置和获取键 Base 和 Derived 的值。

还有其他多种方法可以完成此操作。

2016-03-17 19:52:21