设为首页 加入收藏

TOP

深入理解Lua的全局变量_G以及源码实现
2014-11-23 23:16:53 来源: 作者: 【 】 浏览:5
Tags:深入 理解 Lua 全局 变量 以及 源码 实现

在Lua脚本层,Lua将所有的全局变量保存在一个常规的table中,这个table被称为全局环境,并且将这个table保存在一个全局变量_G中,也就是说在脚本中可以用_G获取这个全局table,并且有_G._G == _G,在默认情况,Lua在全局环境_G中添加了标准库比如math、函数比如pairs等。


可以通过下面代码,可以递归打印_G中的所有信息:


function treaverse_global_env(curtable,level)
for key,value in pairs(curtable or {}) do
local prefix = string.rep(" ",level*5)
print(string.format("%s%s(%s)",prefix,key,type(value)))


--注意死循环
if (type(value) == "table" ) and key ~= "_G" and (not value.package) then
treaverse_global_env(value,level + 1)
elseif (type(value) == "table" ) and (value.package) then
print(string.format("%sSKIPTABLE:%s",prefix,key))
end
end
end


treaverse_global_env(_G,0)


注意Lua虚拟机本身是不会使用_G这个变量的,在脚本中,可以任意改变这个变量_G的值,不会影响任何环境或副作用。比如下面代码:


local cf = loadstring(" local i=0 i=i+1 print(i) ")


--从后面两个输出我们可以看出,生成的函数的环境就是全局_G
print(cf,getfenv(cf),_G) -- function: 0025AF58 table: 00751C68 table: 00751C68


--改变_G的值
_G = {}
cf() --1


--虽然改变了_G的值,但函数的的环境仍然是全局环境table地址仍然是00751C68
print(cf,getfenv(cf),_G) -- function: 0075AF58 table: 00751C68 table: 0075B468


默认情况下,在Lua中当compiles a chunk时,都是以_G作为环境的,当然可以通过函数load或loadfile,改变compiles a chunk时的环境。在C中,可以使用lua_load(类似有luaL_load*作为前缀的辅助函数)


来load a lua chunk,load的后得到的函数,默认情况下,它的第一个upvalue就是_G,我们可以改变第一个upvalue,来改变得到的函数执行环境。


变量_G是在C中注册的(源码linit.c, lbaselib.c中),在C中,可以直接调用lua_pushglobaltable把这个全局环境压入栈中,在lua5.2 该函数实质就是从注册表中获取这个全局环境,即lua_pushglobaltable用下面宏定义的:


#define lua_pushglobaltable(L) lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)


这里的LUA_REGISTRYINDEX是Lua注册表(注册表是lua虚拟机范围内是全局唯一的)的伪索引,LUA_RIDX_GLOBALS是全局环境在注册表中的索引(也就说,全局环境_G是虚拟机范围内是全局唯一的)。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Linux/Unix分配进程ID的方法以及.. 下一篇用Lua实现插入、删除和查找时间复..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: