5.1之前, 全域性變數儲存在_g這個table中, 這樣的操作:
a = 1
相當於:
_g['a'] = 1
但在5.2之後, 引入了_env叫做環境,與_g全域性變數表產生了一些混淆,需要從原理上做乙個理解。
在5.2中,
操作a = 1
相當於_env['a'] = 1
這是乙個最基礎的認知改變,其次要格外注意_env不是全域性變數,而是乙個upvalue(非區域性變數)。
其次,_env['_g']指向了_env自身,這一目的是為了相容5.1之前的版本,因為之前你也許會用到:
_g['a'] = 2 , 在5.2中, 這相當於_env['_g']['a'],為了避免5.1之前的老**在5.2中執行錯誤,所以5.2設定了_env['_g']=_env來相容這個問題。然而你不要忘記_env['_g']=_env,所以一切都順理成章了。
在5.1中,我們可以為一段**塊(或者函式)設定環境,使用函式setfuncs,這樣會導致那一段**/函式訪問全域性變數的時候使用了setfuncs指定的table,而不是全域性的_g。
在5.2中,setfuncs遭到了廢棄,因為引入了_env。 通過在函式定義前覆蓋_env變數即可為函式定義設定乙個全新的環境,比如:
a = 3
function get_echo()
local _env=
return function echo()
print(a)
endend
get_echo()()
會列印2,而不是3,因為echo函式的環境被修改為,而print(a)相當於訪問_env['a'](先忘掉那為了相容而存在的_g)。
這就是_env的基本用法了。
另外,不得不提到lua的c支援中關於全域性變數與環境的細節,只能簡單描述,你必須自己試試才能記得清楚。
lua_setglobal/lua_getglobal都是操作lua_state登錄檔中lua_ridx_globals偽索引指向的全域性變數表,與lua中訪問_env['a']或者a是不同的。
lua_load載入lua**後會返回乙個函式,缺省會給這個函式設定乙個upvalue就叫_env,起值是lua_ridx_globals的全域性變數表,你可以lua_setupvalue設定這個函式的upvalue,即下標1的upvalue,因為這個位置是這個函式的_env表存放位置(你可以通過lua_setupvalue的返回值印證這一點)
這裡巧妙的是,lua_state會在建立時保證lua_ridx_globals的全域性變數表中包含乙個指向自己的_g元素,這樣就保證了在不呼叫lua_setupvalue的情況下該返回函式的_env['_g']是指向自己的,即lua_ridx_globals這個全域性表。(其實你的lua直譯器就是簡單的lua_load後pcall的,對於乙個剛啟動lua_state來說是沒有_env的,是lua直譯器load你的**時自動給帶上的_env,其值是lua_state的lua_ridx_globals全域性表。)
一些有意思的東西是需要你自己摸索的,lua語言自身就很簡練,並且所有東西都不是什麼神秘的事情,可以通過讀原始碼或者試驗摸索得到。
最後,提一下,lua_state啟動後在登錄檔裡lua_ridx_globals下標存放的全域性表一定有乙個元素是指向自己的,即_g.
對lua中 ENV表的理解 lua5 2版本以後
當我拿到 env表的時候,會去想這個 env表是幹什麼用的?首先看如下 1 print env 0x1d005f0 2print g 0x1d005f0 viewcode 看了上面的 就感覺 env表不就是 g表嗎?但 env表是不是全域性的呢?我又列印了 g表的內容 1 for k v in pa...
lua5 2模組註冊
lua 5.2不鼓勵使用lual register把模組註冊到全域性域,而是使用lual newlib。我們首先看下lual newlib,它是乙個巨集,如下 define lual newlib l,l lual newlibtable l,l lual setfuncs l,l,0 lual n...
lua 5 2的 luaL newlib 的用法
對於lua 5.2,lua 5.2是2011年發布的。國內使用5.1的居多。lual register 和lual openlibs。這些功能大多數都廢棄了 lual register這個註冊c 的庫函式,功能被廢棄了。新的api lual newlib 網上的資料不多。下面給出乙個使用 lual ...