找回密码
 立即注册
查看: 228|回复: 0

tolua.setpeer学习记录

[复制链接]
发表于 2023-4-9 11:16 | 显示全部楼层 |阅读模式
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[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);    }    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[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

转载于:https://www.cnblogs.com/xsxjin/p/6854584.html
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-14 04:55 , Processed in 0.087904 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表