Lua:为自定义userdata提供tostring方法

我有一个Lua中的自定义userdata。当我在实例上执行tostring(在Lua内部)时,它始终返回一个字符串,例如"userdata: 0xaddress"。我想要它返回userdata的名称("Point: 0xaddress"),这意味着我想要覆盖tostring并包括我的userdata的情况。是否有人知道是否可以做到这一点?

#define check_point(L) \
    (Point**)luaL_checkudata(L,1,"Point")

static int
luaw_point_getx(lua_State* L)
{
    Point **point_ud = check_point(L);
    lua_pushinteger(L, (*point_ud)->x);
    return 1;
}

static int
luaw_point_gety(lua_State* L)
{
    Point **point_ud = check_point(L);
    lua_pushinteger(L, (*point_ud)->y);
    return 1;
}

void
luaw_point_push(lua_State* L, Point *point)
{
    Point **point_ud = (Point **)lua_newuserdata(L, sizeof(Point *));
    *point_ud = point;
    luaL_getmetatable(L, "Point");
    lua_setmetatable(L, -2);
}

static int
luaw_point_tostring(lua_State* L)
{
    Point **point_ud = check_point(L);
    lua_pushfstring(L, "Point: %p", *point_ud);
    return 1;
}

static const struct luaL_Reg luaw_point_m [] = {
    {"x", luaw_point_getx},
    {"y", luaw_point_gety},
    {"__tostring", luaw_point_tostring},
    {NULL, NULL}
};

int
luaopen_wpoint(lua_State* L)
{
    luaL_newmetatable(L, "WEAVE.Point");
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    luaL_register(L, NULL, luaw_point_m);
    lua_pop(L, 1); /* pop metatable */
    /* return a constructor for Point */
    lua_register(L, "Point", luaw_point_new);
    return 1;
}
点赞
用户734069
用户734069

你需要重写 tostring 函数,以便检查值是否为其自定义类型之一。如果是,则使用自己的函数获取名称。如果不是,则将其传递给覆盖的 tostring 函数。通常通过将原始的 tostring 放置在 upvalue 中,然后用其替换全局的 tostring 来完成这个过程。

2012-10-08 15:38:28
用户1008957
用户1008957

你需要提供一个 __tostring 的元方法,方式类似你编写 __index

// [...]
int luaw_point_index(lua_State* L)
{
    lua_pushfstring(L, "Point: %p", lua_topointer(L, 1));
    return 1;
}

int luaopen_wpoint(lua_State* L)
{
    luaL_newmetatable(L, "WEAVE.Point");
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    lua_pushcfunction(L, luaw_point_index);
    lua_setfield(L, -2, "__tostring");
    luaL_register(L, NULL, luaw_point_m);
    return 1;
}
2012-10-08 15:45:03