lua的metatable查找成员源码分析
来源:互联网 发布:淘宝助理上架教程 编辑:程序博客网 时间:2024/05/29 14:59
lua中如果访问的成员不存在,lua会继续在其对应的metatable中查找。lua中每种数据结构都有metatable,但是只有table和userdata有自己私有的metatable,剩下的数据结构有各自共享的metatable。
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { Table *mt; switch (ttnov(o)) { case LUA_TTABLE: mt = hvalue(o)->metatable; break; case LUA_TUSERDATA: mt = uvalue(o)->metatable; break; default: mt = G(L)->mt[ttnov(o)]; } return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);}
从最后一句的返回值可以看出来metatable必须要有一个叫"__index"的成员,否则metatable的成员查找链无法生效。从table中获取成员的入口函数:
LUA_API int lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2addr(L, idx); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); return ttnov(L->top - 1);}
直接将功能转给了luaV_gettable
#define luaV_gettable(L,t,k,v) { const TValue *slot; \ if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ else luaV_finishget(L,t,k,v,slot); }
这是一个宏定义,首先使用luaV_fastget尝试直接从table中获取成员,如果失败了,再调用luaV_finishget在metatable中查找成员
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, const TValue *slot) { int loop; /* counter to avoid infinite loops */ const TValue *tm; /* metamethod */ for (loop = 0; loop < MAXTAGLOOP; loop++) { if (slot == NULL) { /* 't' is not a table? */ lua_assert(!ttistable(t)); tm = luaT_gettmbyobj(L, t, TM_INDEX); if (ttisnil(tm)) luaG_typeerror(L, t, "index"); /* no metamethod */ /* else will try the metamethod */ } else { /* 't' is a table */ lua_assert(ttisnil(slot)); tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ if (tm == NULL) { /* no metamethod? */ setnilvalue(val); /* result is nil */ return; } /* else will try the metamethod */ } if (ttisfunction(tm)) { /* is metamethod a function? */ luaT_callTM(L, tm, t, key, val, 1); /* call it */ return; } t = tm; /* else try to access 'tm[key]' */ if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ setobj2s(L, val, slot); /* done */ return; } /* else repeat (tail call 'luaV_finishget') */ } luaG_runerror(L, "'__index' chain too long; possible loop");}
为了防止metatable循环嵌套,最多查找MAXTAGLOOP(2000)次,这里获取的tm是metatable的__index成员,如果tm是函数,则直接调用tm,如果是table则在其中查找,如果没有找到则设置t为tm重复这个过程,直到找到或者超过最大次数限制。
0 0
- lua的metatable查找成员源码分析
- lua中metatable源码分析总结
- lua的metatable简介
- lua的metatable讲解
- lua: userdata的metatable使用
- lua metatable
- Lua Metatable
- Metatable lua
- lua metatable
- Lua Metatable
- LUA中的metatable笔记 (metatable的默认元素)
- Lua的Metatable和OOP相关
- lua metatable及其相关方法的简述
- Lua metatable实例
- Metatable In Lua 浅尝辄止
- Metatable In Lua 浅尝辄止
- Metatable In Lua 浅尝辄止
- Metatable In Lua
- 计算给定时间与现在的时间差
- MyEclipse 快捷键
- 使用import简化Spring配置文件
- SpringMVC——Controller和视图之间数据的相互传递
- Android 的状态模式
- lua的metatable查找成员源码分析
- linux sed命令详解
- 如何让页面撑满整个浏览器屏幕
- python 2.7 中文教程-3:非正式教程
- 6月英语学习总结
- php实现qq第三方登录
- cocoa touch——UIPickerView
- LeetCode - 50. Pow(x, n)
- Eclipse调试JDK源代码~watch(监视)变量时报:<error(s)_during_the_evaluation>