lua5 2 帶你理解 ENV和 G

2021-06-27 20:26:06 字數 1608 閱讀 9730

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 ...