2012-10-08 24 views
1

我在lua有一個自定義userdata。當我執行tostring對userdata(在Lua中)的實例時,它總是返回一個字符串,如"userdata: 0xaddress"。我希望它返回userdata的名稱("Point: 0xaddress"),這意味着我想覆蓋tostring以包含我的用戶數據的一個案例。有誰知道這是否可以做到?Lua:給自定義用戶數據一個tostring方法

#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; 
} 

回答

4

您必須提供__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; 
} 
+1

請注意,這隻適用於Lua 5.2。 –

+0

@NicolBolas爲什麼只在Lua 5.2中?它應該工作在Lua 5.1,AFAIK – prapin

+1

因爲這就是5.1的工作原理。只有Lua的'tostring'方法會調用'__tostring'「metamethod」。只需搜索[文檔](http://www.lua.org/manual/5.1/manual.html);唯一要提到的是與Lua的「tostring」方法有關。儘管[5.2的文檔](http://www.lua.org/manual/5.2/manual.html)在* any *字符串轉換例程中提到了它,即使是luaL_tolstring和lua_tostring也是如此'luaL_tolstring'。 –

0

你將不得不覆蓋tostring,以便它檢查是否值是其自定義的類型之一。如果是,則使用自己的函數來獲取名稱。如果不是,則將其傳遞給覆蓋的tostring。這通常是通過將原始tostring置於高價位,然後用此替換全球tostring

相關問題