Lua 常用函數 一

 

lua_getallocf

lua_Alloc lua_getallocf (lua_State *L, void **ud);

返回給定狀態機的內存分配器函數。如果 ud 不是 NULL ,Lua 把調用lua_newstate 時傳入的那個指針放入*ud


lua_getfenv

void lua_getfenv (lua_State *L, int index);

把索引處值的環境表壓入堆棧。


lua_getfield

void lua_getfield (lua_State *L, int index, const char *k);

t[k] 值壓入堆棧,這裏的 t 是指有效索引 index 指向的值。在 Lua 中,這個函數可能觸發對應 "index" 事件的元方法(參見 §2.8)。


lua_getglobal

void lua_getglobal (lua_State *L, const char *name);

把全局變量 name 裏的值壓入堆棧。這個是用一個宏定義出來的:

     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)

lua_getmetatable

int lua_getmetatable (lua_State *L, int index);

把給定索引指向的值的元表壓入堆棧。如果索引無效,或是這個值沒有元表,函數將返回 0 並且不會向棧上壓任何東西。


lua_gettable

void lua_gettable (lua_State *L, int index);

t[k] 值壓入堆棧,這裏的 t 是指有效索引 index 指向的值,而 k 則是棧頂放的值。

這個函數會彈出堆棧上的 key (把結果放在棧上相同位置)。在 Lua 中,這個函數可能觸發對應 "index" 事件的元方法(參見§2.8)。


lua_gettop

int lua_gettop (lua_State *L);

返回棧頂元素的索引。因爲索引是從 1 開始編號的,所以這個結果等於堆棧上的元素個數(因此返回 0 表示堆棧爲空)。


lua_insert

void lua_insert (lua_State *L, int index);

把棧頂元素插入指定的有效索引處,並依次移動這個索引之上的元素。不要用僞索引來調用這個函數,因爲僞索引不是真正指向堆棧上的位置。


lua_Integer

typedef ptrdiff_t lua_Integer;

這個類型被用於 Lua API 接收整數值。

缺省時這個被定義爲 ptrdiff_t ,這個東西通常是機器能處理的最大整數類型。


lua_isboolean

int lua_isboolean (lua_State *L, int index);

當給定索引的值類型爲 boolean 時,返回 1 ,否則返回 0 。


lua_iscfunction

int lua_iscfunction (lua_State *L, int index);

當給定索引的值是一個 C 函數時,返回 1 ,否則返回 0 。


lua_isfunction

int lua_isfunction (lua_State *L, int index);

當給定索引的值是一個函數( C 或 Lua 函數均可)時,返回 1 ,否則返回 0 。


lua_islightuserdata

int lua_islightuserdata (lua_State *L, int index);

當給定索引的值是一個 light userdata 時,返回 1 ,否則返回 0 。


lua_isnil

int lua_isnil (lua_State *L, int index);

當給定索引的值是 nil 時,返回 1 ,否則返回 0 。


lua_isnumber

int lua_isnumber (lua_State *L, int index);

當給定索引的值是一個數字,或是一個可轉換爲數字的字符串時,返回 1 ,否則返回 0 。


lua_isstring

int lua_isstring (lua_State *L, int index);

當給定索引的值是一個字符串或是一個數字(數字總能轉換成字符串)時,返回 1 ,否則返回 0 。


lua_istable

int lua_istable (lua_State *L, int index);

當給定索引的值是一個 table 時,返回 1 ,否則返回 0 。


lua_isthread

int lua_isthread (lua_State *L, int index);

當給定索引的值是一個 thread 時,返回 1 ,否則返回 0 。


lua_isuserdata

int lua_isuserdata (lua_State *L, int index);

當給定索引的值是一個 userdata (無論是完整的 userdata 還是 light userdata )時,返回 1 ,否則返回 0 。


lua_lessthan

int lua_lessthan (lua_State *L, int index1, int index2);

如果索引 index1 處的值小於索引 index2 處的值時,返回 1 ;否則返回 0 。其語義遵循 Lua 中的< 操作符(就是說,有可能調用元方法)。如果任何一個索引無效,也會返回 0 。


lua_load

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname);

加載一個 Lua chunk 。如果沒有錯誤, lua_load 把一個編譯好的 chunk 作爲一個 Lua 函數壓入堆棧。否則,壓入出錯信息。 lua_load 的返回值可以是:

這個函數僅僅加栽 chunk ;而不會去運行它。

lua_load 會自動檢測 chunk 是文本的還是二進制的,然後做對應的加載操作(參見程序luac)。

lua_load 函數使用一個用戶提供的reader 函數來讀取 chunk (參見lua_Reader)。data 參數會被傳入讀取器函數。

chunkname 這個參數可以賦予 chunk 一個名字,這個名字被用於出錯信息和調試信息(參見§3.8)。


lua_newstate

lua_State *lua_newstate (lua_Alloc f, void *ud);

創建的一個新的獨立的狀態機。如果創建不了(因爲內存問題)返回 NULL 。參數 f 是一個分配器函數; Lua 將通過這個函數做狀態機內所有的內存分配操作。第二個參數 ud ,這個指針將在每次調用分配器時被直接傳入。


lua_newtable

void lua_newtable (lua_State *L);

創建一個空 table ,並將之壓入堆棧。它等價於 lua_createtable(L, 0, 0)


lua_newthread

lua_State *lua_newthread (lua_State *L);

創建一個新線程,並將其壓入堆棧,並返回維護這個線程的 lua_State 指針。這個函數返回的新狀態機共享原有狀態機中的所有對象(比如一些 table),但是它有獨立的執行堆棧。

沒有顯式的函數可以用來關閉或銷燬掉一個線程。線程跟其它 Lua 對象一樣是垃圾收集的條目之一。


lua_newuserdata

void *lua_newuserdata (lua_State *L, size_t size);

這個函數分配分配一塊指定大小的內存塊,把內存塊地址作爲一個完整的 userdata 壓入堆棧,並返回這個地址。

userdata 代表 Lua 中的 C 值。完整的 userdata 代表一塊內存。它是一個對象(就像 table 那樣的對象):你必須創建它,它有着自己的元表,而且它在被回收時,可以被監測到。一個完整的 userdata 只和它自己相等(在等於的原生作用下)。

當 Lua 通過 gc 元方法回收一個完整的 userdata 時, Lua 調用這個元方法並把 userdata 標記爲已終止。等到這個 userdata 再次被收集的時候,Lua 會釋放掉相關的內存。


lua_next

int lua_next (lua_State *L, int index);

從棧上彈出一個 key(鍵),然後把索引指定的表中 key-value(健值)對壓入堆棧(指定 key 後面的下一 (next) 對)。如果表中以無更多元素,那麼lua_next 將返回 0 (什麼也不壓入堆棧)。

典型的遍歷方法是這樣的:

     /* table 放在索引 't' 處 */
     lua_pushnil(L);  /* 第一個 key */
     while (lua_next(L, t) != 0) {
       /* 用一下 'key' (在索引 -2 處) 和 'value' (在索引 -1 處) */
       printf("%s - %s\n",
              lua_typename(L, lua_type(L, -2)),
              lua_typename(L, lua_type(L, -1)));
       /* 移除 'value' ;保留 'key' 做下一次迭代 */
       lua_pop(L, 1);
     }

在遍歷一張表的時候,不要直接對 key 調用 lua_tolstring ,除非你知道這個 key 一定是一個字符串。調用 lua_tolstring 有可能改變給定索引位置的值;這會對下一次調用 lua_next 造成影響。


lua_Number

typedef double lua_Number;

Lua 中數字的類型。確省是 double ,但是你可以在 luaconf.h 中修改它。

通過修改配置文件你可以改變 Lua 讓它操作其它數字類型(例如:float 或是 long )。


lua_objlen

size_t lua_objlen (lua_State *L, int index);

返回指定的索引處的值的長度。對於 string ,那就是字符串的長度;對於 table ,是取長度操作符 ('#') 的結果;對於 userdata ,就是爲其分配的內存塊的尺寸;對於其它值,爲 0 。


lua_pcall

lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);

以保護模式調用一個函數。

nargsnresults 的含義與 lua_call 中的相同。如果在調用過程中沒有發生錯誤, lua_pcall 的行爲和 lua_call 完全一致。但是,如果有錯誤發生的話, lua_pcall 會捕獲它,然後把單一的值(錯誤信息)壓入堆棧,然後返回錯誤碼。同 lua_call 一樣, lua_pcall 總是把函數本身和它的參數從棧上移除。

如果 errfunc 是 0 ,返回在棧頂的錯誤信息就和原始錯誤信息完全一致。否則,errfunc 就被當成是錯誤處理函數在棧上的索引。(在當前的實現裏,這個索引不能是僞索引。)在發生運行時錯誤時,這個函數會被調用而參數就是錯誤信息。錯誤處理函數的返回值將被lua_pcall 作爲出錯信息返回在堆棧上。

典型的用法中,錯誤處理函數被用來在出錯信息上加上更多的調試信息,比如棧跟蹤信息 (stack traceback) 。這些信息在lua_pcall 返回後,因爲棧已經展開 (unwound) ,所以收集不到了。

lua_pcall 函數在調用成功時返回 0 ,否則返回以下(定義在lua.h 中的)錯誤代碼中的一個:

  • LUA_ERRRUN: 運行時錯誤。
  • LUA_ERRMEM: 內存分配錯誤。 對於這種錯,Lua 調用不了錯誤處理函數。
  • LUA_ERRERR: 在運行錯誤處理函數時發生的錯誤。

lua_pop

void lua_pop (lua_State *L, int n);

從堆棧中彈出 n 個元素。


lua_pushboolean

void lua_pushboolean (lua_State *L, int b);

b 作爲一個 boolean 值壓入堆棧。


lua_pushcclosure

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);

把一個新的 C closure 壓入堆棧。

當創建了一個 C 函數後,你可以給它關聯一些值,這樣就是在創建一個 C closure (參見 §3.4);接下來無論函數何時被調用,這些值都可以被這個函數訪問到。爲了將一些值關聯到一個 C 函數上,首先這些值需要先被壓入堆棧(如果有多個值,第一個先壓)。接下來調用lua_pushcclosure 來創建出 closure 並把這個 C 函數壓到堆棧上。參數n 告之函數有多少個值需要關聯到函數上。lua_pushcclosure 也會把這些值從棧上彈出。


lua_pushcfunction

void lua_pushcfunction (lua_State *L, lua_CFunction f);

將一個 C 函數壓入堆棧。這個函數接收一個 C 函數指針,並將一個類型爲 function 的 Lua 值壓入堆棧。當這個棧頂的值被調用時,將觸發對應的 C 函數。

註冊到 Lua 中的任何函數都必須遵循正確的協議來接收參數和返回值(參見 lua_CFunction)。

lua_pushcfunction 是作爲一個宏定義出現的:

     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)

lua_pushfstring

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

把一個格式化過的字符串壓入堆棧,然後返回這個字符串的指針。它和 C 函數 sprintf 比較像,不過有一些重要的區別:

  • 摸你需要爲結果分配空間: 其結果是一個 Lua 字符串,由 Lua 來關心其內存分配 (同時通過垃圾收集來釋放內存)。
  • 這個轉換非常的受限。 不支持 flag ,寬度,或是指定精度。 它只支持下面這些: '%%' (插入一個 '%'), '%s' (插入一個帶零終止符的字符串,沒有長度限制), '%f' (插入一個lua_Number), '%p' (插入一個指針或是一個十六進制數), '%d' (插入一個int), '%c' (把一個int 作爲一個字符插入)。

lua_pushinteger

void lua_pushinteger (lua_State *L, lua_Integer n);

n 作爲一個數字壓棧。


lua_pushlightuserdata

void lua_pushlightuserdata (lua_State *L, void *p);

把一個 light userdata 壓棧。

userdata 在 Lua 中表示一個 C 值。 light userdata 表示一個指針。它是一個像數字一樣的值:你不需要專門創建它,它也沒有獨立的 metatable ,而且也不會被收集(因爲從來不需要創建)。只要表示的 C 地址相同,兩個 light userdata 就相等。


lua_pushlstring

void lua_pushlstring (lua_State *L, const char *s, size_t len);

把指針 s 指向的長度爲 len 的字符串壓棧。 Lua 對這個字符串做一次內存拷貝(或是複用一個拷貝),因此s 處的內存在函數返回後,可以釋放掉或是重用於其它用途。字符串內可以保存有零字符。


lua_pushnil

void lua_pushnil (lua_State *L);

把一個 nil 壓棧。


lua_pushnumber

void lua_pushnumber (lua_State *L, lua_Number n);

把一個數字 n 壓棧。


lua_pushstring

void lua_pushstring (lua_State *L, const char *s);

把指針 s 指向的以零結尾的字符串壓棧。 Lua 對這個字符串做一次內存拷貝(或是複用一個拷貝),因此s 處的內存在函數返回後,可以釋放掉或是重用於其它用途。字符串中不能包含有零字符;第一個碰到的零字符會認爲是字符串的結束。


lua_pushthread

int lua_pushthread (lua_State *L);

L 中提供的線程壓棧。如果這個線程是當前狀態機的主線程的話,返回 1 。


lua_pushvalue

void lua_pushvalue (lua_State *L, int index);

把堆棧上給定有效處索引處的元素作一個拷貝壓棧。


lua_pushvfstring

const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);

等價於 lua_pushfstring,不過是用 va_list 接收參數,而不是用可變數量的實際參數。


lua_rawequal

int lua_rawequal (lua_State *L, int index1, int index2);

如果兩個索引 index1index2 處的值簡單地相等(不調用元方法)則返回 1 。否則返回 0 。如果任何一個索引無效也返回 0 。


lua_rawget

void lua_rawget (lua_State *L, int index);

類似於 lua_gettable,但是作一次直接訪問(不觸發元方法)。


lua_rawgeti

void lua_rawgeti (lua_State *L, int index, int n);

t[n] 的值壓棧,這裏的 t 是指給定索引 index 處的一個值。這是一個直接訪問;就是說,它不會觸發元方法。


lua_rawset

void lua_rawset (lua_State *L, int index);

類似於 lua_settable,但是是作一個直接賦值(不觸發元方法)。


lua_rawseti

void lua_rawseti (lua_State *L, int index, int n);

等價於 t[n] = v,這裏的 t 是指給定索引 index 處的一個值,而 v 是棧頂的值。

函數將把這個值彈出棧。賦值操作是直接的;就是說,不會觸發元方法。


lua_Reader

typedef const char * (*lua_Reader) (lua_State *L,
                                    void *data,
                                    size_t *size);

lua_load 用到的讀取器函數,每次它需要一塊新的 chunk 的時候,lua_load 就調用讀取器,每次都會傳入一個參數data 。讀取器需要返回含有新的 chunk 的一塊內存的指針,並把 size 設爲這塊內存的大小。內存塊必須在下一次函數被調用之前一直存在。讀取器可以通過返回一個NULL 來指示 chunk 結束。讀取器可能返回多個塊,每個塊可以有任意的大於零的尺寸。


lua_register

void lua_register (lua_State *L,
                   const char *name,
                   lua_CFunction f);

把 C 函數 f 設到全局變量 name 中。它通過一個宏定義:

     #define lua_register(L,n,f) \
            (lua_pushcfunction(L, f), lua_setglobal(L, n))

lua_remove

void lua_remove (lua_State *L, int index);

從給定有效索引處移除一個元素,把這個索引之上的所有元素移下來填補上這個空隙。不能用僞索引來調用這個函數,因爲僞索引並不指向真實的棧上的位置。


lua_replace

void lua_replace (lua_State *L, int index);

把棧頂元素移動到給定位置(並且把這個棧頂元素彈出),不移動任何元素(因此在那個位置處的值被覆蓋掉)。


lua_resume

int lua_resume (lua_State *L, int narg);

在給定線程中啓動或繼續一個 coroutine 。

要啓動一個 coroutine 的話,首先你要創建一個新線程(參見 lua_newthread );然後把主函數和若干參數壓到新線程的堆棧上;最後調用 lua_resume ,把 narg 設爲參數的個數。這次調用會在 coroutine 掛起時或是結束運行後返回。當函數返回時,堆棧中會有傳給lua_yield 的所有值,或是主函數的所有返回值。如果 coroutine 切換時,lua_resume 返回LUA_YIELD ,而當 coroutine 結束運行且沒有任何錯誤時,返回 0 。如果有錯則返回錯誤代碼(參見lua_pcall)。在發生錯誤的情況下,堆棧沒有展開,因此你可以使用 debug API 來處理它。出錯信息放在棧頂。要繼續運行一個 coroutine 的話,你把需要傳給yield 作結果的返回值壓入堆棧,然後調用lua_resume


lua_setallocf

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);

把指定狀態機的分配器函數換成帶上指針 udf


lua_setfenv

int lua_setfenv (lua_State *L, int index);

從堆棧上彈出一個 table 並把它設爲指定索引處值的新環境。如果指定索引處的值即不是函數又不是線程或是 userdata ,lua_setfenv 會返回 0 ,否則返回 1 。


lua_setfield

void lua_setfield (lua_State *L, int index, const char *k);

做一個等價於 t[k] = v 的操作,這裏 t 是給出的有效索引index 處的值,而v 是棧頂的那個值。

這個函數將把這個值彈出堆棧。跟在 Lua 中一樣,這個函數可能觸發一個 "newindex" 事件的元方法(參見§2.8)。


lua_setglobal

void lua_setglobal (lua_State *L, const char *name);

從堆棧上彈出一個值,並將其設到全局變量 name 中。它由一個宏定義出來:

     #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)

lua_setmetatable

int lua_setmetatable (lua_State *L, int index);

把一個 table 彈出堆棧,並將其設爲給定索引處的值的 metatable 。


lua_settable

void lua_settable (lua_State *L, int index);

作一個等價於 t[k] = v 的操作,這裏 t 是一個給定有效索引index 處的值,v 指棧頂的值,而 k 是棧頂之下的那個值。

這個函數會把鍵和值都從堆棧中彈出。和在 Lua 中一樣,這個函數可能觸發 "newindex" 事件的元方法(參見§2.8)。


lua_settop

void lua_settop (lua_State *L, int index);

參數允許傳入任何可接受的索引以及 0 。它將把堆棧的棧頂設爲這個索引。如果新的棧頂比原來的大,超出部分的新元素將被填爲nil 。如果index 爲 0 ,把棧上所有元素移除。


lua_State

typedef struct lua_State lua_State;

一個不透明的結構,它保存了整個 Lua 解釋器的狀態。 Lua 庫是完全可重入的:它沒有任何全局變量。(譯註:從 C 語法上來說,也不盡然。例如,在 table 的實現中用了一個靜態全局變量 dummynode_ ,但這在正確使用時並不影響可重入性。只是萬一你錯誤鏈接了 lua 庫,不小心在同一進程空間中存在兩份 lua 庫實現的代碼的話,多份 dummynode_ 不同的地址會導致一些問題。)所有的信息都保存在這個結構中。

這個狀態機的指針必須作爲第一個參數傳遞給每一個庫函數。 lua_newstate 是一個例外,這個函數會從頭創建一個 Lua 狀態機。


lua_status

int lua_status (lua_State *L);

返回線程 L 的狀態。

正常的線程狀態是 0 。當線程執行完畢或發生一個錯誤時,狀態值是錯誤碼。如果線程被掛起,狀態爲 LUA_YIELD


lua_toboolean

int lua_toboolean (lua_State *L, int index);

把指定的索引處的的 Lua 值轉換爲一個 C 中的 boolean 值( 0 或是 1 )。和 Lua 中做的所有測試一樣,lua_toboolean 會把任何不同於falsenil 的值當作 1 返回;否則就返回 0 。如果用一個無效索引去調用也會返回 0 。(如果你想只接收真正的 boolean 值,就需要使用lua_isboolean 來測試值的類型。)


lua_tocfunction

lua_CFunction lua_tocfunction (lua_State *L, int index);

把給定索引處的 Lua 值轉換爲一個 C 函數。這個值必須是一個 C 函數;如果不是就返回 NULL


lua_tointeger

lua_Integer lua_tointeger (lua_State *L, int idx);

把給定索引處的 Lua 值轉換爲 lua_Integer 這樣一個有符號整數類型。這個 Lua 值必須是一個數字或是一個可以轉換爲數字的字符串(參見 §2.2.1);否則,lua_tointeger 返回 0 。

如果數字不是一個整數,截斷小數部分的方式沒有被明確定義。


lua_tolstring

const char *lua_tolstring (lua_State *L, int index, size_t *len);

把給定索引處的 Lua 值轉換爲一個 C 字符串。如果 len 不爲 NULL ,它還把字符串長度設到*len 中。這個 Lua 值必須是一個字符串或是一個數字;否則返回返回NULL 。如果值是一個數字,lua_tolstring 還會把堆棧中的那個值的實際類型轉換爲一個字符串。(當遍歷一個表的時候,把lua_tolstring 作用在鍵上,這個轉換有可能導致lua_next 弄錯。)

lua_tolstring 返回 Lua 狀態機中字符串的以對齊指針。這個字符串總能保證 ( C 要求的)最後一個字符爲零 ('\0') ,而且它允許在字符串內包含多個這樣的零。因爲 Lua 中可能發生垃圾收集,所以不保證lua_tolstring 返回的指針,在對應的值從堆棧中移除後依然有效。


lua_tonumber

lua_Number lua_tonumber (lua_State *L, int index);

把給定索引處的 Lua 值轉換爲 lua_Number 這樣一個 C 類型(參見 lua_Number )。這個 Lua 值必須是一個數字或是一個可轉換爲數字的字符串(參見 §2.2.1 );否則,lua_tonumber 返回 0 。


lua_topointer

const void *lua_topointer (lua_State *L, int index);

把給定索引處的值轉換爲一般的 C 指針 (void*) 。這個值可以是一個 userdata ,table ,thread 或是一個 function ;否則,lua_topointer 返回NULL 。不同的對象有不同的指針。不存在把指針再轉回原有類型的方法。

這個函數通常只爲產生 debug 信息用。


lua_tostring

const char *lua_tostring (lua_State *L, int index);

等價於 lua_tolstring ,而參數 len 設爲 NULL


lua_tothread

lua_State *lua_tothread (lua_State *L, int index);

把給定索引處的值轉換爲一個 Lua 線程(由 lua_State* 代表)。這個值必須是一個線程;否則函數返回NULL


lua_touserdata

void *lua_touserdata (lua_State *L, int index);

如果給定索引處的值是一個完整的 userdata ,函數返回內存塊的地址。如果值是一個 light userdata ,那麼就返回它表示的指針。否則,返回NULL


lua_type

int lua_type (lua_State *L, int index);

返回給定索引處的值的類型,當索引無效時則返回 LUA_TNONE (那是指一個指向堆棧上的空位置的索引)。lua_type 返回的類型是一些個在lua.h 中定義的常量:LUA_TNILLUA_TNUMBERLUA_TBOOLEANLUA_TSTRINGLUA_TTABLELUA_TFUNCTIONLUA_TUSERDATALUA_TTHREADLUA_TLIGHTUSERDATA


lua_typename

const char *lua_typename  (lua_State *L, int tp);

返回 tp 表示的類型名,這個 tp 必須是 lua_type 可能返回的值中之一。


lua_Writer

typedef int (*lua_Writer) (lua_State *L,
                           const void* p,
                           size_t sz,
                           void* ud);

lua_dump 用到的寫入器函數。每次 lua_dump 產生了一塊新的 chunk ,它都會調用寫入器。傳入要寫入的緩存 (p) 和它的尺寸 (sz) ,還有lua_dump 的參數data

寫入器會返回一個錯誤碼: 0 表示沒有錯誤;別的值均表示一個錯誤,並且會讓 lua_dump 停止再次調用寫入器。


lua_xmove

void lua_xmove (lua_State *from, lua_State *to, int n);

傳遞 同一個 全局狀態機下不同線程中的值。

這個函數會從 from 的堆棧中彈出 n 個值,然後把它們壓入to 的堆棧中。


lua_yield

int lua_yield  (lua_State *L, int nresults);

切出一個 coroutine 。

這個函數只能在一個 C 函數的返回表達式中調用。如下:

     return lua_yield (L, nresults);

當一個 C 函數這樣調用 lua_yield ,正在運行中的 coroutine 將從運行中掛起,然後啓動這個 coroutine 用的那次對 lua_resume 的調用就返回了。參數 nresults 指的是堆棧中需要返回的結果個數,這些返回值將被傳遞給lua_resume

3.8 - 調試接口

Lua 沒有內建的調試設施。取而代之的是提供了一些函數接口和鉤子。利用這些接口,可以做出一些不同類型的調試器,性能分析器,或是其它一些需要從解釋器中取到“內部信息”的工具。


lua_Debug

typedef struct lua_Debug {
  int event;
  const char *name;           /* (n) */
  const char *namewhat;       /* (n) */
  const char *what;           /* (S) */
  const char *source;         /* (S) */
  int currentline;            /* (l) */
  int nups;                   /* (u) upvalue 個數 */
  int linedefined;            /* (S) */
  int lastlinedefined;        /* (S) */
  char short_src[LUA_IDSIZE]; /* (S) */
  /* 私有部分 */
  其它域
} lua_Debug;

一個用來攜帶活動中函數的各種信息的結構。 lua_getstack 僅填寫這個結構中的私有部分,這些部分以後會用到。調用 lua_getinfo 則可以填上 lua_Debug 中有用信息的那些域。

lua_Debug 中的各個域有下列含義:

  • source: 如果函數是定義在一個字符串中,source 就是這個字符串。 如果函數定義在一個文件中,source 是一個以 '@' 開頭的文件名。
  • short_src: 一個“可打印版本”的 source,用於出錯信息。
  • linedefined: 函數定義開始處的行號。
  • lastlinedefined: 函數定義結束處的行號。
  • what: 如果函數是一個 Lua 函數,則爲一個字符串 "Lua" ; 如果是一個 C 函數,則爲"C"; 如果它是一個 chunk 的主體部分,則爲"main"; 如果是一個作了尾調用的函數,則爲 "tail" 。 別的情況下,Lua 沒有關於函數的別的信息。
  • currentline: 給定函數正在執行的那一行。 當提供不了行號信息的時候,currentline 被設爲 -1 。
  • name: 給定函數的一個合理的名字。 因爲 Lua 中的函數也是一個值, 所以它們沒有固定的名字: 一些函數可能是全局複合變量的值, 另一些可能僅僅只是被保存在一個 table 中。lua_getinfo 函數會檢查函數是這樣被調用的,以此來找到一個適合的名字。 如果它找不到名字,name 就被設置爲NULL
  • namewhat: 結實 name 域。 namewhat 的值可以是"global","local", "method", "field","upvalue", 或是"" (空串)。 這取決於函數怎樣被調用。 (Lua 用空串表示其它選項都不符合)
  • nups: 函數的 upvalue 的個數。

lua_gethook

lua_Hook lua_gethook (lua_State *L);

返回當前的鉤子函數。


lua_gethookcount

int lua_gethookcount (lua_State *L);

返回當前鉤子記數。


lua_gethookmask

int lua_gethookmask (lua_State *L);

返回當前的鉤子掩碼 (mask) 。


lua_getinfo

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

返回一個指定的函數或函數調用的信息。

當用於取得一次函數調用的信息時,參數 ar 必須是一個有效的活動的記錄。這條記錄可以是前一次調用lua_getstack 得到的,或是一個鉤子 (參見lua_Hook)得到的參數。

用於獲取一個函數的信息時,可以把這個函數壓入堆棧,然後把 what 字符串以字符 '>' 起頭。(這個情況下,lua_getinfo 從棧頂上彈出函數。)例如,想知道函數f 在哪一行定義的,你可以下下列代碼:

     lua_Debug ar;
     lua_getfield(L, LUA_GLOBALSINDEX, "f");  /* 取到全局變量 'f' */
     lua_getinfo(L, ">S", &ar);
     printf("%d\n", ar.linedefined);

what 字符串中的每個字符都篩選出結構 ar 結構中一些域用於填充,或是把一個值壓入堆棧:

  • 'n': 填充 namenamewhat 域;
  • 'S': 填充 sourceshort_srclinedefinedlastlinedefined,以及 what 域;
  • 'l': 填充 currentline 域;
  • 'u': 填充 nups 域;
  • 'f': 把正在運行中指定級別處函數壓入堆棧; (譯註:一般用於獲取函數調用中的信息, 級別是由 ar 中的私有部分來提供。 如果用於獲取靜態函數,那麼就直接把指定函數重新壓回堆棧, 但這樣做通常無甚意義。)
  • 'L': 壓一個 table 入棧,這個 table 中的整數索引用於描述函數中哪些行是有效行。 (有效行指有實際代碼的行, 即你可以置入斷點的行。 無效行包括空行和只有註釋的行。)

這個函數出錯會返回 0 (例如,what 中有一個無效選項)。


lua_getlocal

const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);

從給定活動記錄中獲取一個局部變量的信息。參數 ar 必須是一個有效的活動的記錄。這條記錄可以是前一次調用lua_getstack 得到的,或是一個鉤子 (參見lua_Hook)得到的參數。索引n 用於選擇要檢閱哪個局部變量( 1 表示第一個參數或是激活的第一個局部變量,以此類推,直到最後一個局部變量)。 lua_getlocal 把變量的值壓入堆棧並返回它的名字。

以 '(' (正小括號)開始的變量指內部變量(循環控制變量,臨時變量,C 函數局部變量)。

當索引大於局部變量的個數時,返回 NULL (什麼也不壓入)。


lua_getstack

int lua_getstack (lua_State *L, int level, lua_Debug *ar);

獲取解釋器的運行時棧的信息。

這個函數用正在運行中的給定級別處的函數的活動記錄來填寫 lua_Debug 結構的一部分。 0 級表示當前運行的函數,而 n+1 級處的函數就是調用第 n 級函數的那一個。如果沒有錯誤,lua_getstack 返回 1 ;當調用傳入的級別大於堆棧深度的時候,返回 0 。


lua_getupvalue

const char *lua_getupvalue (lua_State *L, int funcindex, int n);

獲取一個 closure 的 upvalue 信息。(對於 Lua 函數,upvalue 是函數需要使用的外部局部變量,因此這些變量被包含在 closure 中。)lua_getupvalue 獲取第n 個 upvalue ,把這個 upvalue 的值壓入堆棧,並且返回它的名字。 funcindex 指向堆棧上 closure 的位置。( 因爲 upvalue 在整個函數中都有效,所以它們沒有特別的次序。因此,它們以字母次序來編號。)

當索引號比 upvalue 數量大的時候,返回 NULL (而且不會壓入任何東西)對於 C 函數,這個函數用空串"" 表示所有 upvalue 的名字。


lua_Hook

typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);

用於調試的鉤子函數類型。

無論何時鉤子被調用,它的參數 ar 中的 event 域都被設爲觸發鉤子的事件。 Lua 把這些事件定義爲以下常量:LUA_HOOKCALLLUA_HOOKRET, LUA_HOOKTAILRETLUA_HOOKLINE, andLUA_HOOKCOUNT。除此之外,對於 line 事件,currentline 域也被設置。要想獲得ar 中的其他域,鉤子必須調用lua_getinfo。對於返回事件,event 的正常值可能是LUA_HOOKRET,或者是LUA_HOOKTAILRET 。對於後一種情況,Lua 會對一個函數做的尾調用也模擬出一個返回事件出來;對於這個模擬的返回事件,調用lua_getinfo 沒有什麼作用。

當 Lua 運行在一個鉤子內部時,它將屏蔽掉其它對鉤子的調用。也就是說,如果一個鉤子函數內再調回 Lua 來執行一個函數或是一個 chunk ,這個執行操作不會觸發任何的鉤子。


lua_sethook

int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

設置一個調試用鉤子函數。

參數 f 是鉤子函數。 mask 指定在哪些事件時會調用:它由下列一組位常量構成LUA_MASKCALLLUA_MASKRETLUA_MASKLINE,以及LUA_MASKCOUNT。參數count 只在 mask 中包含有LUA_MASKCOUNT 纔有意義。對於每個事件,鉤子被調用的情況解釋如下:

  • call hook: 在解釋器調用一個函數時被調用。 鉤子將於 Lua 進入一個新函數後,函數獲取參數前被調用。
  • return hook: 在解釋器從一個函數中返回時調用。 鉤子將於 Lua 離開函數之前的那一刻被調用。 你無權訪問被函數返回出去的那些值。(譯註:原文 (You have no access to the values to be returned by the function) 如此。 但“無權訪問”一詞值得商榷。 某些情況下你可以訪問到一些被命名爲 (*temporary) 的局部變量, 那些索引被排在最後的 (*temporary) 變量指的就是返回值。 但是由於 Lua 對特殊情況做了一些優化,比如直接返回一個被命名的局部變量, 那麼就找不到對應的 (*temporary) 變量了。本質上,返回值一定存在於此刻的局部變量中, 並且可以訪問它,只是無法確定是哪些罷了。至於這個時候函數體內的其它局部變量, 是不保證有效的。進入 return hook 的那一刻起,實際已經退出函數內部的運行環節, 返回值佔用的局部變量空間以後的部分,都有可能因 hook 本身複用它們而改變。)
  • line hook: 在解釋器準備開始執行新的一行代碼時, 或是跳轉到這行代碼中時(即使在同一行內跳轉)被調用。 (這個事件僅僅在 Lua 執行一個 Lua 函數時發生。)
  • count hook: 在解釋器每執行 count 條指令後被調用。 (這個事件僅僅在 Lua 執行一個 Lua 函數時發生。)

鉤子可以通過設置 mask 爲零屏蔽。

lua_setlocal

const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);

設置給定活動記錄中的局部變量的值。參數 arn lua_getlocal 中的一樣(參見 lua_getlocal)。 lua_setlocal 把棧頂的值賦給變量然後返回變量的名字。它會將值從棧頂彈出。

當索引大於局部變量的個數時,返回 NULL (什麼也不彈出)。


 

lua_setupvalue

const char *lua_setupvalue (lua_State *L, int funcindex, int n);

設置 closure 的 upvalue 的值。它把棧頂的值彈出並賦於 upvalue 並返回 upvalue 的名字。參數funcindexn lua_getupvalue 中的一樣(參見 lua_getupvalue)。

當索引大於 upvalue 的個數時,返回 NULL (什麼也不彈出)。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章