1. 程式人生 > >tolua.setpeer學習記錄

tolua.setpeer學習記錄

lua 記錄 如果 進棧 get string use 輕量 peer

static int tolua_bnd_setpeer(lua_State *L) 
{
    // stack: userdata, table
    if (!lua_isuserdata(L, -2)) 
    {
        return luaL_error(L, "Invalid argument #1 to setpeer: userdata expected.");        
    }

    if (lua_isnil(L, 2)) 
    {
        lua_pop(L, 1);
        lua_pushvalue(L, TOLUA_NOPEER);
        lua_setfenv(L, 
-2); } else { lua_pushvalue(L, 2); //stack: u p p lua_setfenv(L, -3); //stack: u p lua_newtable(L); //stack: u p vt lua_pushlightuserdata(L, &vptr); //stack: u p vt lu lua_pushvalue(L, 1
); //stack: u p vt lu u lua_rawset(L, -3); //stack: u p vt @vt[lu] = u //lua_pushvalue(L, 1); //lua_rawseti(L, -2, 1); lua_getref(L, LUA_RIDX_VPTR); //stack: u p vt mt lua_setmetatable(L, -2); //stack: u p vt lua_pushstring(L,
"base"); //stack: u p vt "base" lua_pushvalue(L, -2); //stack: u p vt "base" vt lua_rawset(L, 2); //stack: u p vt lua_pop(L, 1); } return 0; };

如果userdata(u)和peer(p)表都不為空的話,會執行如下步驟:

1.lua_pushvalue(L, 2); 把peer表復制壓進棧頂         此時虛擬棧:stack: u, p, p

2.lua_setfenv(L, -3);     -3是u的位置,相當於把棧頂元素peer設置為u的環境表         此時虛擬棧:stack: u, p 

3.lua_newtable(L);      創建一個空的table,壓進棧頂                      此時虛擬棧:stack: u, p,vt

4.lua_pushlightuserdata(L, &vptr); 把一個輕量級的userdata壓進棧頂,vptr是一個值為1的static int類型 此時虛擬棧:stack: u, p,vt, lu

5.lua_pushvalue(L, 1);          把棧底元素u復制壓進棧頂                       此時虛擬棧:stack: u, p,vt, lu, u

6.lua_rawset(L, -3); 執行vt[lu] = u, 直接賦值,忽略元表                  此時虛擬棧:stack: u, p,vt

7.lua_getref(L, LUA_RIDX_VPTR); 通過ref獲取對應的一個table,壓進棧頂 此時虛擬棧:stack: u, p,vt, mt

8.lua_setmetatable(L, -2); setmetatable(p, mt) 此時虛擬棧:stack: u, p,vt

9.lua_pushstring(L, "base"); 把"base"字符串壓進棧頂 此時虛擬棧:stack: u, p,vt,"base"

10.lua_pushvalue(L, -2);         把vt表壓進棧頂                            此時虛擬棧:stack: u, p,vt,"base",vt

11.lua_rawset(L, 2);           p.base = vt 此時虛擬棧:stack: u, p,vt

12.lua_pop(L, 1);             把vt彈出棧頂                             此時虛擬棧:stack: u, p

tolua.setpeer學習記錄