1
votes

I have a custom userdata in lua. When I execute tostring on an instance of the userdata (inside Lua), it always returns a string like "userdata: 0xaddress". I would like it to return the name of the userdata ("Point: 0xaddress"), meaning that I want to override the tostring to include a case for my userdata. Does anyone know if this can be done?

#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 const struct luaL_Reg luaw_point_m [] = {
    {"x", luaw_point_getx},
    {"y", luaw_point_gety},
    {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);
    return 1;
}
2

2 Answers

4
votes

You have to provide a __tostring metamethod, in the similar way you wrote the __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;
}
0
votes

You will have to override tostring so that it checks to see if the value is one of its custom types. If it is, then use your own function to get the name. If not, pass it to the overridden tostring. This is generally done by putting the original tostring in an upvalue and then replacing the global tostring with that.