在Lua腳本層,Lua將所有的全局變量保存在一個常規的table中,這個table被稱為全局環境,並且將這個table保存在一個全局變量_G中,也就是說在腳本中可以用_G獲取這個全局table,並且有_G._G == _G,在默認情況,Lua在全局環境_G中添加了標准庫比如math、函數比如pairs等。
Lua 語言 15 分鐘快速入門 http://www.linuxidc.com/Linux/2013-06/86582.htm
Lua程序設計(第2版)中文 PDF http://www.linuxidc.com/Linux/2013-03/81833.htm
Lua程序設計(第二版)閱讀筆記 http://www.linuxidc.com/Linux/2013-03/81834.htm
NetBSD 將支持用 Lua 腳本開發內核組件 http://www.linuxidc.com/Linux/2013-02/79527.htm
CentOS 編譯安裝 Lua LuaSocket http://www.linuxidc.com/Linux/2011-08/41105.htm
可以通過下面代碼,可以遞歸打印_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是虛擬機范圍內是全局唯一的)。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-05/102528p2.htm