BlaXuan 发表于 2023-4-9 11:16

tolua.setpeer学习记录

staticint tolua_bnd_setpeer(lua_State *L) {    // stack: userdata, tableif (!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 = 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);    }    return0;};
把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,会进行以下步骤:
  (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 = 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

转载于:https://www.cnblogs.com/xsxjin/p/6854584.html
页: [1]
查看完整版本: tolua.setpeer学习记录