Lua库中同时存在对象方法和字段

编辑:事实证明这在Lua中是不可能的,既有 __index 方法又有类实例方法。它要么是这个,要么是那个。

尝试使我的Lua接口工作,支持字段和类实例方法。看起来通过操作初始化,我只能让函数 (_f)或方法(_m)生效,但不能两者同时生效。

我感觉我错过了一个非常简单的问题。

初始化库的方式:

void PushUserdata(const void *data, const char *metatable)
{
    const void **wrapped_ptr = (const void**)lua_newuserdata(l, sizeof(const void*));
    *wrapped_ptr = data;
    luaL_getmetatable(l, metatable);
    lua_setmetatable(l, -2);
}

static int player_head(lua_State *L)
{
    if (!Player::playerHead)
        lua_pushnil(L);
    else
        PushUserdata(Player::playerHead, "player");

    return 1;
}

static int playerget(lua_State *L)
{
    Player *player = *CHECKPLAYER(L, 1); // 获取双指针并解引用以获取真正的指针

    const char *field = luaL_checkstring(L, 2);

    if (!strcmp(field, "next"))
    {
        if (!player->next)
            lua_pushnil(L);
        else
            PushUserdata(player->next, "player");
    }
    else if (!strcmp(field, "prev"))
    {
        if (!player->prev)
            lua_pushnil(L);
        else
            PushUserdata(player->prev, "player");
    }
    else if (!strcmp(field, "obj"))
    {
        if (!player->obj)
            lua_pushnil(L);
        else
            PushUserdata(player->obj, "wobj");
    }
    else if (!strcmp(field, "AddCollisionObjHook")) // 如果 __index 在下面的表中,就会走到这里
    {
    }
    else
        return 0;

    return 1;
}

static const struct luaL_Reg playerlib_f[] = {
    {"head", player_head},
    {"AddPreThinker", AddPreThinker},
    {"AddPostThinker", AddPostThinker},
    {NULL, NULL}
};

static const struct luaL_Reg playerlib_m[] = {
    {"__tostring", player2string},
    {"__index", playerget},
    {"__newindex", playerset},
    {"AddCollisionObjHook", AddCollisionObjHook},
    {NULL, NULL}
};

int Lua_PlayerLib(lua_State *L)
{
    luaL_newmetatable(L, "player");
    lua_pushvalue(L, -1); // 复制元表,但为什么?
    luaL_setfuncs(L, playerlib_m, 0);
    luaL_newlib(L, playerlib_f, 0);
    lua_setglobal(L, "player");

    return 1;
}

Lua脚本:

me = playerlib.head()
me:AddCollisionObjHook(playerHitObj)

错误消息:

警告:[string "postload.lua"]: 尝试调用方法' AddCollisionObjHook'(一个空值)

'me'绝对是一个有效的非空值。

原文链接 https://stackoverflow.com/questions/69058649

点赞