tolua.setpeer學習記錄


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

把C#對象在lua中對應的userdata(csobj)和一個lua table(peer)進行setpeer操作后:tolua.setpeer(csobj, peer)

1.把peer表設置為csobj的環境表,peer.base[&vptr] = csobj,  setmetatable(peer.base, vptrtable)

2.在csobj訪問一個元素,csobj[key],會進行以下步驟:

  (1)在peer表直接查找,rawget(peer, key),如果不為nil, 則返回這個值。如果為nil,則進行第(2)不查找

 

 

 

如果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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM