<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 4 – 編程接口 這個部分描述了 Lua 的 C API , 也就是宿主程序跟 Lua 通訊用的一組 C 函數。 所有的 API 函數按相關的類型以及常量都聲明在頭文件 `lua.h` 中。 雖然我們說的是“函數”, 但一部分簡單的 API 是以宏的形式提供的。 除非另有說明, 所有的這些宏都只使用它們的參數一次 (除了第一個參數,那一定是 Lua 狀態), 因此你不需擔心這些宏的展開會引起一些副作用。 C 庫中所有的 Lua API 函數都不去檢查參數是否相容及有效。 然而,你可以在編譯 Lua 時加上打開一個宏開關 `LUA_USE_APICHECK` 來改變這個行為。 ## 4.1 – 棧 Lua 使用一個 _虛擬棧_ 來和 C 互傳值。 棧上的的每個元素都是一個 Lua 值 (**nil**,數字,字符串,等等)。 無論何時 Lua 調用 C,被調用的函數都得到一個新的棧, 這個棧獨立于 C 函數本身的棧,也獨立于之前的 Lua 棧。 它里面包含了 Lua 傳遞給 C 函數的所有參數, 而 C 函數則把要返回的結果放入這個棧以返回給調用者 (參見 [`lua_CFunction`](#lua_CFunction))。 方便起見, 所有針對棧的 API 查詢操作都不嚴格遵循棧的操作規則。 而是可以用一個 _索引_ 來指向棧上的任何元素: 正的索引指的是棧上的絕對位置(從1開始); 負的索引則指從棧頂開始的偏移量。 展開來說,如果堆棧有 _n_ 個元素, 那么索引 1 表示第一個元素 (也就是最先被壓棧的元素) 而索引 _n_ 則指最后一個元素; 索引 -1 也是指最后一個元素 (即棧頂的元素), 索引 _-n_ 是指第一個元素。 ## 4.2 – 棧大小 當你使用 Lua API 時, 就有責任保證做恰當的調用。 特別需要注意的是, _你有責任控制不要堆棧溢出_。 你可以使用 [`lua_checkstack`](#lua_checkstack) 這個函數來擴大可用堆棧的尺寸。 無論何時 Lua 調用 C , 它都只保證至少有 `LUA_MINSTACK` 這么多的堆棧空間可以使用。 `LUA_MINSTACK` 一般被定義為 20 , 因此,只要你不是不斷的把數據壓棧, 通常你不用關心堆棧大小。 當你調用一個 Lua 函數卻沒有指定要接收多少個返回值時 (參見 [`lua_call`](#lua_call)), Lua 可以保證棧一定有足夠的空間來接收所有的返回值, 但不保證此外留有額外的空間。 因此,在做了一次這樣的調用后,如果你需要繼續壓棧, 則需要使用 [`lua_checkstack`](#lua_checkstack)。 ## 4.3 – 有效索引與可接受索引 API 中的函數若需要傳入棧索引,這個索引必須是 _有效索引_ 或是 _可接受索引_。 _有效索引_ 指引用棧內真實位置的索引; 即在 1 到棧頂之間的位置 (`1 ≤ abs(index) ≤ top`)。 通常,一個可能修改該位置的值的函數需要傳入有效索引。 除非另有說明, 任何可以接受有效索引的函數同時也接受 _偽索引_。 偽索引指代一些可以被 C code 訪問得到 Lua 值,而它們又不在棧內。 這用于訪問注冊表以及 C 函數的上值(參見 [§4.4](#4.4))。 對于那些只是需要棧中的值(例如查詢函數) 而不需要指定一個棧位置的函數, 可以用一個可接受的索引去調用它們。 _可接受索引_ 不僅可以是任何包括偽索引在內的有效索引, 還可以是任何超過棧頂但落在為棧分配出來的空間內的正索引。 (注意 0 永遠都不是一個可接受索引。) 除非另有說明,API 里的函數都接受可接受索引。 允許可接受索引是為了避免對棧頂以外的查詢時做額外的檢查。 例如,C 函數可以直接查詢傳給它的第三個參數, 而不用先檢查是不是有第三個參數, 即不需要檢查 3 是不是一個有效索引。 對于那些以可接受索引調用的函數, 無效索引被看作包含了一個虛擬類型 `LUA_TNONE` 的值, 這個值的行為和 nil 一致。 ## 4.4 – C 閉包 當 C 函數被創建出來, 我們有可能會把一些值關聯在一起, 也就是創建一個 _C 閉包_ (參見 [`lua_pushcclosure`](#lua_pushcclosure)); 這些被關聯起來的值被叫做 _上值_ , 它們可以在函數被調用的時候訪問的到。 無論何時去調用 C 函數, 函數的上值都可以用偽索引定位。 我們可以用 [`lua_upvalueindex`](#lua_upvalueindex) 這個宏來生成這些偽索引。 第一個關聯到函數的值放在 `lua_upvalueindex(1)` 位置處,依此類推。 使用 `lua_upvalueindex(_n_)` 時, 若 _n_ 大于當前函數的總上值個數 (但不可以大于 256)會產生一個可接受的但無效的索引。 ## 4.5 – 注冊表 Lua 提供了一個 _注冊表_, 這是一個預定義出來的表, 可以用來保存任何 C 代碼想保存的 Lua 值。 這個表可以用有效偽索引 `LUA_REGISTRYINDEX` 來定位。 任何 C 庫都可以在這張表里保存數據, 為了防止沖突,你需要特別小心的選擇鍵名。 一般的用法是,你可以用一個包含你的庫名的字符串做為鍵名, 或者取你自己 C 對象的地址,以輕量用戶數據的形式做鍵, 還可以用你的代碼創建出來的任意 Lua 對象做鍵。 關于變量名,字符串鍵名中以下劃線加大寫字母的名字被 Lua 保留。 注冊表中的整數鍵用于引用機制 (參見 [`luaL_ref`](#luaL_ref)), 以及一些預定義的值。 因此,整數鍵不要用于別的目的。 當你創建了一個新的 Lua 狀態機, 其中的注冊表內就預定義好了幾個值。 這些預定義值可以用整數索引到, 這些整數以常數形式定義在 `lua.h` 中。 有下列常數: * **`LUA_RIDX_MAINTHREAD`:** 注冊表中這個索引下是狀態機的主線程。 (主線程和狀態機同時被創建出來。) * **`LUA_RIDX_GLOBALS`:** 注冊表的這個索引下是全局環境。 ## 4.6 – C 中的錯誤處理 在內部實現中,Lua 使用了 C 的 `longjmp` 機制來處理錯誤。 (如果你使用 C++ 編譯,Lua 將換成異常; 細節請在源代碼中搜索 `LUAI_THROW`。) 當 Lua 碰到任何錯誤 (比如內存分配錯誤、類型錯誤、語法錯誤、還有運行時錯誤) 它都會 _拋出_一個錯誤出去; 也就是調用一次長跳轉。 在 _保護環境_ 下, Lua 使用 `setjmp` 來設置一個恢復點; 任何發生的錯誤都會跳轉到最近的一個恢復點。 如果錯誤發生在保護環境之外, Lua 會先調用 _panic 函數_ (參見 [`lua_atpanic`](#lua_atpanic)) 然后調用 `abort` 來退出宿主程序。 你的 panic 函數只要不返回 (例如:長跳轉到你在 Lua 外你自己設置的恢復點) 就可以不退出程序。 panic 函數以錯誤消息處理器(參見 [§2.3](#2.3))的方式運行; 錯誤消息在棧頂。 不同的是,它不保證棧空間。 做任何壓棧操作前,panic 函數都必須先檢查是否有足夠的空間 (參見 [§4.2](#4.2))。 大多數 API 函數都有可能拋出錯誤, 例如在內存分配錯誤時就會拋出。 每個函數的文檔都會注明它是否可能拋出錯誤。 在 C 函數內部,你可以通過調用 [`lua_error`](#lua_error) 來拋出錯誤。 ## 4.7 – C 中的讓出處理 Lua 內部使用 C 的 `longjmp` 機制讓出一個協程。 因此,如果一個 C 函數 `foo` 調用了一個 API 函數, 而這個 API 函數讓出了(直接或間接調用了讓出函數)。 由于 `longjmp` 會移除 C 棧的棧幀, Lua 就無法返回到 `foo` 里了。 為了回避這類問題, 碰到 API 調用中調用讓出時,除了那些拋出錯誤的 API 外,還提供了三個函數: [`lua_yieldk`](#lua_yieldk), [`lua_callk`](#lua_callk),和 [`lua_pcallk`](#lua_pcallk) 。 它們在讓出發生時,可以從傳入的 _延續函數_ (名為 `k` 的參數)繼續運行。 我們需要預設一些術語來解釋延續點。 對于從 Lua 中調用的 C 函數,我們稱之為 _原函數_。 從這個原函數中調用的上面所述的三個 C API 函數我們稱之為 _被調函數_。 被調函數可以使當前線程讓出。 (讓出發生在被調函數是 [`lua_yieldk`](#lua_yieldk), 或傳入 [`lua_callk`](#lua_callk) 或 [`lua_pcallk`](#lua_pcallk) 的函數調用了讓出時。) 假設正在運行的線程在執行被調函數時讓出。 當再次延續這條線程,它希望繼續被調函數的運行。 然而,被調函數不可能返回到原函數中。 這是因為之前的讓出操作破壞了 C 棧的棧幀。 作為替代品,Lua 調用那個作為被調函數參數給出的 _延續函數_ 。 正如其名,延續函數將延續原函數的任務。 下面的函數會做一個說明: ``` int original_function (lua_State *L) { ... /* code 1 */ status = lua_pcall(L, n, m, h); /* calls Lua */ ... /* code 2 */ } ``` 現在我們想允許被 [`lua_pcall`](#lua_pcall) 運行的 Lua 代碼讓出。 首先,我們把函數改寫成這個樣子: ``` int k (lua_State *L, int status, lua_KContext ctx) { ... /* code 2 */ } int original_function (lua_State *L) { ... /* code 1 */ return k(L, lua_pcall(L, n, m, h), ctx); } ``` 上面的代碼中,新函數 `k` 就是一個 _延續函數_ (函數類型為 [`lua_KFunction`](#lua_KFunction))。 它的工作就是原函數中調用 [`lua_pcall`](#lua_pcall) 之后做的那些事情。 現在我們必須通知 Lua 說,你必須在被 [`lua_pcall`](#lua_pcall) 執行的 Lua 代碼發生過中斷(錯誤或讓出)后, 還得繼續調用 `k` 。 所以我們還得繼續改寫這段代碼,把 [`lua_pcall`](#lua_pcall) 替換成 [`lua_pcallk`](#lua_pcallk): ``` int original_function (lua_State *L) { ... /* code 1 */ return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1); } ``` 注意這里那個額外的顯式的對延續函數的調用: Lua 僅在需要時,這可能是由錯誤導致的也可能是發生了讓出而需要繼續運行,才會調用延續函數。 如果沒有發生過任何讓出,調用的函數正常返回, 那么 [`lua_pcallk`](#lua_pcallk) (以及 [`lua_callk`](#lua_callk))也會正常返回。 (當然,這個例子中你也可以不在之后調用延續函數, 而是在原函數的調用后直接寫上需要做的工作。) 除了 Lua 狀態,延續函數還有兩個參數: 一個是調用最后的狀態碼,另一個一開始由 [`lua_pcallk`](#lua_pcallk) 傳入的上下文 (`ctx`)。 (Lua 本身不使用這個值;它僅僅從原函數轉發這個值給延續函數。) 對于 [`lua_pcallk`](#lua_pcallk) 而言, 狀態碼和 [`lua_pcallk`](#lua_pcallk) 本應返回值相同,區別僅在于發生過讓出后才執行完時,狀態碼為 [`LUA_YIELD`](#pdf-LUA_YIELD)(而不是 [`LUA_OK`](#pdf-LUA_OK))。 對于 [`lua_yieldk`](#lua_yieldk) 和 [`lua_callk`](#lua_callk) 而言, 調用延續函數傳入的狀態碼一定是 [`LUA_YIELD`](#pdf-LUA_YIELD)。 (對這兩個函數,Lua 不會因任何錯誤而調用延續函數。 因為它們并不處理錯誤。) 同樣,當你使用 [`lua_callk`](#lua_callk) 時, 你應該用 [`LUA_OK`](#pdf-LUA_OK) 作為狀態碼來調用延續函數。 (對于 [`lua_yieldk`](#lua_yieldk), 幾乎沒有什么地方需要直接調用延續函數, 因為 [`lua_yieldk`](#lua_yieldk) 本身并不會返回。) Lua 會把延續函數看作原函數。 延續函數將接收到和原函數相同的 Lua 棧,其接收到的 lua 狀態也和 被調函數若返回后應該有的狀態一致。 (例如, [`lua_callk`](#lua_callk) 調用之后, 棧中之前壓入的函數和調用參數都被調用產生的返回值所替代。) 這時也有相同的上值。 等到它返回的時候,Lua 會將其看待成原函數的返回去操作。 ## 4.8 – 函數和類型 這里按字母次序列出了所有 C API 中的函數和類型。 每個函數都有一個這樣的提示: [-o, +p, _x_] 對于第一個域,`o`, 指的是該函數會從棧上彈出多少個元素。 第二個域,`p`, 指該函數會將多少個元素壓棧。 (所有函數都會在彈出參數后再把結果壓棧。) `x|y` 這種形式的域表示該函數根據具體情況可能壓入(或彈出) `x` 或 `y` 個元素; 問號 '`?`' 表示 我們無法僅通過參數來了解該函數會彈出/壓入多少元素 (比如,數量取決于棧上有些什么)。 第三個域,`x`, 解釋了該函數是否會拋出錯誤: '`-`' 表示該函數絕對不會拋出錯誤; '`e`' 表示該函數可能拋出錯誤; '`v`' 表示該函數可能拋出有意義的錯誤。 ### `lua_absindex` [-0, +0, –] ``` int lua_absindex (lua_State *L, int idx); ``` 將一個可接受的索引 `idx` 轉換為絕對索引 (即,一個不依賴棧頂在哪的值)。 ### `lua_Alloc` ``` typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); ``` Lua 狀態機中使用的內存分配器函數的類型。 內存分配函數必須提供一個功能類似于 `realloc` 但又不完全相同的函數。 它的參數有 `ud` ,一個由 [`lua_newstate`](#lua_newstate) 傳給它的指針; `ptr` ,一個指向已分配出來/將被重新分配/要釋放的內存塊指針; `osize` ,內存塊原來的尺寸或是關于什么將被分配出來的代碼; `nsize` ,新內存塊的尺寸。 如果 `ptr` 不是 `NULL`, `osize` 是 `ptr` 指向的內存塊的尺寸, 即這個內存塊當初被分配或重分配的尺寸。 如果 `ptr` 是 `NULL`, `osize` 是 Lua 即將分配對象類型的編碼。 當(且僅當)Lua 創建一個對應類型的新對象時, `osize` 是 [`LUA_TSTRING`](#pdf-LUA_TSTRING),[`LUA_TTABLE`](#pdf-LUA_TTABLE),[`LUA_TFUNCTION`](#pdf-LUA_TFUNCTION), [`LUA_TUSERDATA`](#pdf-LUA_TUSERDATA),或 [`LUA_TTHREAD`](#pdf-LUA_TTHREAD) 中的一個。 若 `osize` 是其它類型,Lua 將為其它東西分配內存。 Lua 假定分配器函數會遵循以下行為: 當 `nsize` 是零時, 分配器必須和 `free` 行為類似并返回 `NULL`。 當 `nsize` 不是零時, 分配器必須和 `realloc` 行為類似。 如果分配器無法完成請求,返回 `NULL`。 Lua 假定在 `osize &gt;= nsize` 成立的條件下, 分配器絕不會失敗。 這里有一個簡單的分配器函數的實現。 這個實現被放在補充庫中,供 [`luaL_newstate`](#luaL_newstate) 使用。 ``` static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { (void)ud; (void)osize; /* not used */ if (nsize == 0) { free(ptr); return NULL; } else return realloc(ptr, nsize); } ``` 注意,標準 C 能確保 `free(NULL)` 沒有副作用, 且 `realloc(NULL,size)` 等價于 `malloc(size)`。 這段代碼假定 `realloc` 在縮小塊長度時不會失敗。 (雖然標準 C 沒有對此行為做出保證,但這看起來是一個安全的假定。) ### `lua_arith` [-(2|1), +1, _e_] ``` void lua_arith (lua_State *L, int op); ``` 對棧頂的兩個值(或者一個,比如取反)做一次數學或位操作。 其中,棧頂的那個值是第二個操作數。 它會彈出壓入的值,并把結果放在棧頂。 這個函數遵循 Lua 對應的操作符運算規則 (即有可能觸發元方法)。 `op` 的值必須是下列常量中的一個: * **`LUA_OPADD`:** 加法 (`+`) * **`LUA_OPSUB`:** 減法 (`-`) * **`LUA_OPMUL`:** 乘法 (`*`) * **`LUA_OPDIV`:** 浮點除法 (`/`) * **`LUA_OPIDIV`:** 向下取整的除法 (`//`) * **`LUA_OPMOD`:** 取模 (`%`) * **`LUA_OPPOW`:** 乘方 (`^`) * **`LUA_OPUNM`:** 取負 (一元 `-`) * **`LUA_OPBNOT`:** 按位取反 (`~`) * **`LUA_OPBAND`:** 按位與 (`&`) * **`LUA_OPBOR`:** 按位或 (`|`) * **`LUA_OPBXOR`:** 按位異或 (`~`) * **`LUA_OPSHL`:** 左移 (`&lt;&lt;`) * **`LUA_OPSHR`:** 右移 (`&gt;&gt;`) ### `lua_atpanic` [-0, +0, –] ``` lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); ``` 設置一個新的 panic 函數,并返回之前設置的那個。 (參見 [§4.6](#4.6))。 ### `lua_call` [-(nargs+1), +nresults, _e_] ``` void lua_call (lua_State *L, int nargs, int nresults); ``` 調用一個函數。 要調用一個函數請遵循以下協議: 首先,要調用的函數應該被壓入棧; 接著,把需要傳遞給這個函數的參數按正序壓棧; 這是指第一個參數首先壓棧。 最后調用一下 [`lua_call`](#lua_call); `nargs` 是你壓入棧的參數個數。 當函數調用完畢后,所有的參數以及函數本身都會出棧。 而函數的返回值這時則被壓棧。 返回值的個數將被調整為 `nresults` 個, 除非 `nresults` 被設置成 `LUA_MULTRET`。 在這種情況下,所有的返回值都被壓入堆棧中。 Lua 會保證返回值都放入棧空間中。 函數返回值將按正序壓棧(第一個返回值首先壓棧), 因此在調用結束后,最后一個返回值將被放在棧頂。 被調用函數內發生的錯誤將(通過 `longjmp` )一直上拋。 下面的例子中,這行 Lua 代碼等價于在宿主程序中用 C 代碼做一些工作: ``` a = f("how", t.x, 14) ``` 這里是 C 里的代碼: ``` lua_getglobal(L, "f"); /* function to be called */ lua_pushliteral(L, "how"); /* 1st argument */ lua_getglobal(L, "t"); /* table to be indexed */ lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */ lua_remove(L, -2); /* remove 't' from the stack */ lua_pushinteger(L, 14); /* 3rd argument */ lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */ lua_setglobal(L, "a"); /* set global 'a' */ ``` 注意上面這段代碼是 _平衡_ 的: 到了最后,堆棧恢復成原有的配置。 這是一種良好的編程習慣。 ### `lua_callk` [-(nargs + 1), +nresults, _e_] ``` void lua_callk (lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k); ``` 這個函數的行為和 [`lua_call`](#lua_call) 完全一致,只不過它還允許被調用的函數讓出 (參見 [§4.7](#4.7))。 ### `lua_CFunction` ``` typedef int (*lua_CFunction) (lua_State *L); ``` C 函數的類型。 為了正確的和 Lua 通訊, C 函數必須使用下列協議。 這個協議定義了參數以及返回值傳遞方法: C 函數通過 Lua 中的棧來接受參數, 參數以正序入棧(第一個參數首先入棧)。 因此,當函數開始的時候, `lua_gettop(L)` 可以返回函數收到的參數個數。 第一個參數(如果有的話)在索引 1 的地方, 而最后一個參數在索引 `lua_gettop(L)` 處。 當需要向 Lua 返回值的時候, C 函數只需要把它們以正序壓到堆棧上(第一個返回值最先壓入), 然后返回這些返回值的個數。 在這些返回值之下的,堆棧上的東西都會被 Lua 丟掉。 和 Lua 函數一樣,從 Lua 中調用 C 函數也可以有很多返回值。 下面這個例子中的函數將接收若干數字參數,并返回它們的平均數與和: ``` static int foo (lua_State *L) { int n = lua_gettop(L); /* 參數的個數 */ lua_Number sum = 0.0; int i; for (i = 1; i <= n; i++) { if (!lua_isnumber(L, i)) { lua_pushliteral(L, "incorrect argument"); lua_error(L); } sum += lua_tonumber(L, i); } lua_pushnumber(L, sum/n); /* 第一個返回值 */ lua_pushnumber(L, sum); /* 第二個返回值 */ return 2; /* 返回值的個數 */ } ``` ### `lua_checkstack` [-0, +0, –] ``` int lua_checkstack (lua_State *L, int n); ``` 確保堆棧上至少有 `n` 個額外空位。 如果不能把堆棧擴展到相應的尺寸,函數返回假。 失敗的原因包括將把棧擴展到比固定最大尺寸還大 (至少是幾千個元素)或分配內存失敗。 這個函數永遠不會縮小堆棧; 如果堆棧已經比需要的大了,那么就保持原樣。 ### `lua_close` [-0, +0, –] ``` void lua_close (lua_State *L); ``` 銷毀指定 Lua 狀態機中的所有對象 (如果有垃圾收集相關的元方法的話,會調用它們), 并且釋放狀態機中使用的所有動態內存。 在一些平臺上,你可以不必調用這個函數, 因為當宿主程序結束的時候,所有的資源就自然被釋放掉了。 另一方面,長期運行的程序,比如一個后臺程序或是一個網站服務器, 會創建出多個 Lua 狀態機。那么就應該在不需要時趕緊關閉它們。 ### `lua_compare` [-0, +0, _e_] ``` int lua_compare (lua_State *L, int index1, int index2, int op); ``` 比較兩個 Lua 值。 當索引 `index1` 處的值通過 `op` 和索引 `index2` 處的值做比較后條件滿足,函數返回 1 。 這個函數遵循 Lua 對應的操作規則(即有可能觸發元方法)。 反之,函數返回 0。 當任何一個索引無效時,函數也會返回 0 。 `op` 值必須是下列常量中的一個: * **`LUA_OPEQ`:** 相等比較 (`==`) * **`LUA_OPLT`:** 小于比較 (`&lt;`) * **`LUA_OPLE`:** 小于等于比較 (`&lt;=`) ### `lua_concat` [-n, +1, _e_] ``` void lua_concat (lua_State *L, int n); ``` 連接棧頂的 `n` 個值, 然后將這些值出棧,并把結果放在棧頂。 如果 `n` 為 1 ,結果就是那個值放在棧上(即,函數什么都不做); 如果 `n` 為 0 ,結果是一個空串。 連接依照 Lua 中通常語義完成(參見 [§3.4.6](#3.4.6) )。 ### `lua_copy` [-0, +0, –] ``` void lua_copy (lua_State *L, int fromidx, int toidx); ``` 從索引 `fromidx` 處復制一個值到一個有效索引 `toidx` 處,覆蓋那里的原有值。 不會影響其它位置的值。 ### `lua_createtable` [-0, +1, _e_] ``` void lua_createtable (lua_State *L, int narr, int nrec); ``` 創建一張新的空表壓棧。 參數 `narr` 建議了這張表作為序列使用時會有多少個元素; 參數 `nrec` 建議了這張表可能擁有多少序列之外的元素。 Lua 會使用這些建議來預分配這張新表。 如果你知道這張表用途的更多信息,預分配可以提高性能。 否則,你可以使用函數 [`lua_newtable`](#lua_newtable) 。 ### `lua_dump` [-0, +0, _e_] ``` int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip); ``` 把函數導出成二進制代碼塊 。 函數接收棧頂的 Lua 函數做參數, 然后生成它的二進制代碼塊。 若被導出的東西被再次加載, 加載的結果就相當于原來的函數。 當它在產生代碼塊的時候, [`lua_dump`](#lua_dump) 通過調用函數 `writer` (參見 [`lua_Writer`](#lua_Writer) ) 來寫入數據,后面的 `data` 參數會被傳入 `writer` 。 如果 `strip` 為真, 二進制代碼塊將不包含該函數的調試信息。 最后一次由 `writer` 的返回值將作為這個函數的返回值返回; 0 表示沒有錯誤。 該函數不會把 Lua 函數彈出堆棧。 ### `lua_error` [-1, +0, _v_] ``` int lua_error (lua_State *L); ``` 以棧頂的值作為錯誤對象,拋出一個 Lua 錯誤。 這個函數將做一次長跳轉,所以一定不會返回 (參見 [`luaL_error`](#luaL_error))。 ### `lua_gc` [-0, +0, _e_] ``` int lua_gc (lua_State *L, int what, int data); ``` 控制垃圾收集器。 這個函數根據其參數 `what` 發起幾種不同的任務: * **`LUA_GCSTOP`:** 停止垃圾收集器。 * **`LUA_GCRESTART`:** 重啟垃圾收集器。 * **`LUA_GCCOLLECT`:** 發起一次完整的垃圾收集循環。 * **`LUA_GCCOUNT`:** 返回 Lua 使用的內存總量(以 K 字節為單位)。 * **`LUA_GCCOUNTB`:** 返回當前內存使用量除以 1024 的余數。 * **`LUA_GCSTEP`:** 發起一步增量垃圾收集。 * **`LUA_GCSETPAUSE`:** 把 `data` 設為 _垃圾收集器間歇率_ (參見 [§2.5](#2.5)),并返回之前設置的值。 * **`LUA_GCSETSTEPMUL`:** 把 `data` 設為 _垃圾收集器步進倍率_ (參見 [§2.5](#2.5)),并返回之前設置的值。 * **`LUA_GCISRUNNING`:** 返回收集器是否在運行(即沒有停止)。 關于這些選項的細節,參見 [`collectgarbage`](#pdf-collectgarbage) 。 ### `lua_getallocf` [-0, +0, –] ``` lua_Alloc lua_getallocf (lua_State *L, void **ud); ``` 返回給定狀態機的內存分配器函數。 如果 `ud` 不是 `NULL` , Lua 把設置內存分配函數時設置的那個指針置入 `*ud` 。 ### `lua_getfield` [-0, +1, _e_] ``` int lua_getfield (lua_State *L, int index, const char *k); ``` 把 `t[k]` 的值壓棧, 這里的 `t` 是索引指向的值。 在 Lua 中,這個函數可能觸發對應 "index" 事件對應的元方法 (參見 [§2.4](#2.4) )。 函數將返回壓入值的類型。 ### `lua_getextraspace` [-0, +0, –] ``` void *lua_getextraspace (lua_State *L); ``` 返回一個 Lua 狀態機中關聯的內存塊指針。 程序可以把這塊內存用于任何用途;而 Lua 不會使用它。 每一個新線程都會攜帶一塊內存, 初始化為主線程的這塊內存的副本。 默認配置下,這塊內存的大小為空指針的大小。 不過你可以重新編譯 Lua 設定這塊內存不同的大小。 (參見 `luaconf.h` 中的 `LUA_EXTRASPACE`。) ### `lua_getglobal` [-0, +1, _e_] ``` int lua_getglobal (lua_State *L, const char *name); ``` 把全局變量 &lt;name&gt;name&lt;/name&gt; 里的值壓棧,返回該值的類型。 ### `lua_geti` [-0, +1, _e_] ``` int lua_geti (lua_State *L, int index, lua_Integer i); ``` 把 `t[i]` 的值壓棧, 這里的 `t` 指給定的索引指代的值。 和在 Lua 里一樣,這個函數可能會觸發 "index" 事件的元方法 (參見 [§2.4](#2.4))。 返回壓入值的類型。 ### `lua_getmetatable` [-0, +(0|1), –] ``` int lua_getmetatable (lua_State *L, int index); ``` 如果該索引處的值有元表,則將其元表壓棧,返回 1 。 否則不會將任何東西入棧,返回 0 。 ### `lua_gettable` [-1, +1, _e_] ``` int lua_gettable (lua_State *L, int index); ``` 把 `t[k]` 的值壓棧, 這里的 `t` 是指索引指向的值, 而 `k` 則是棧頂放的值。 這個函數會彈出堆棧上的鍵,把結果放在棧上相同位置。 和在 Lua 中一樣, 這個函數可能觸發對應 "index" 事件的元方法 (參見 [§2.4](#2.4) )。 返回壓入值的類型。 ### `lua_gettop` [-0, +0, –] ``` int lua_gettop (lua_State *L); ``` 返回棧頂元素的索引。 因為索引是從 1 開始編號的, 所以這個結果等于棧上的元素個數; 特別指出,0 表示棧為空。 ### `lua_getuservalue` [-0, +1, –] ``` int lua_getuservalue (lua_State *L, int index); ``` 將給定索引處的用戶數據所關聯的 Lua 值壓棧。 返回壓入值的類型。 ### `lua_insert` [-1, +1, –] ``` void lua_insert (lua_State *L, int index); ``` 把棧頂元素移動到指定的有效索引處, 依次移動這個索引之上的元素。 不要用偽索引來調用這個函數, 因為偽索引沒有真正指向棧上的位置。 ### `lua_Integer` ``` typedef ... lua_Integer; ``` Lua 中的整數類型。 缺省時,這個就是 `long long`, (通常是一個 64 位以二為補碼的整數), 也可以修改它為 `long` 或 `int` (通常是一個 32 位以二為補碼的整數)。 (參見 `luaconf.h` 中的 `LUA_INT` 。) Lua 定義了兩個常量: `LUA_MININTEGER` 和 `LUA_MAXINTEGER` 來表示這個類型可以表示的最小和最大值。 ### `lua_isboolean` [-0, +0, –] ``` int lua_isboolean (lua_State *L, int index); ``` 當給定索引的值是一個布爾量時,返回 1 ,否則返回 0 。 ### `lua_iscfunction` [-0, +0, –] ``` int lua_iscfunction (lua_State *L, int index); ``` 當給定索引的值是一個 C 函數時,返回 1 ,否則返回 0 。 ### `lua_isfunction` [-0, +0, –] ``` int lua_isfunction (lua_State *L, int index); ``` 當給定索引的值是一個函數( C 或 Lua 函數均可)時,返回 1 ,否則返回 0 。 ### `lua_isinteger` [-0, +0, –] ``` int lua_isinteger (lua_State *L, int index); ``` 當給定索引的值是一個整數 (其值是一個數字,且內部以整數儲存), 時,返回 1 ,否則返回 0 。 ### `lua_islightuserdata` [-0, +0, –] ``` int lua_islightuserdata (lua_State *L, int index); ``` 當給定索引的值是一個輕量用戶數據時,返回 1 ,否則返回 0 。 ### `lua_isnil` [-0, +0, –] ``` int lua_isnil (lua_State *L, int index); ``` 當給定索引的值是 **nil** 時,返回 1 ,否則返回 0 。 ### `lua_isnone` [-0, +0, –] ``` int lua_isnone (lua_State *L, int index); ``` 當給定索引無效時,返回 1 ,否則返回 0 。 ### `lua_isnoneornil` [-0, +0, –] ``` int lua_isnoneornil (lua_State *L, int index); ``` 當給定索引無效或其值是 **nil** 時, 返回 1 ,否則返回 0 。 ### `lua_isnumber` [-0, +0, –] ``` int lua_isnumber (lua_State *L, int index); ``` 當給定索引的值是一個數字,或是一個可轉換為數字的字符串時,返回 1 ,否則返回 0 。 ### `lua_isstring` [-0, +0, –] ``` int lua_isstring (lua_State *L, int index); ``` 當給定索引的值是一個字符串或是一個數字 (數字總能轉換成字符串)時,返回 1 ,否則返回 0 。 ### `lua_istable` [-0, +0, –] ``` int lua_istable (lua_State *L, int index); ``` 當給定索引的值是一張表時,返回 1 ,否則返回 0 。 ### `lua_isthread` [-0, +0, –] ``` int lua_isthread (lua_State *L, int index); ``` 當給定索引的值是一條線程時,返回 1 ,否則返回 0 。 ### `lua_isuserdata` [-0, +0, –] ``` int lua_isuserdata (lua_State *L, int index); ``` 當給定索引的值是一個用戶數據(無論是完全的還是輕量的)時, 返回 1 ,否則返回 0 。 ### `lua_isyieldable` [-0, +0, –] ``` int lua_isyieldable (lua_State *L); ``` 如果給定的協程可以讓出,返回 1 ,否則返回 0 。 ### `lua_KContext` ``` typedef ... lua_KContext; ``` 延續函數上下文參數的類型。 這一定是一個數字類型。 當有 `intptr_t` 時,被定義為 `intptr_t` , 因此它也可以保存指針。 否則,它被定義為 `ptrdiff_t`。 ### `lua_KFunction` ``` typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); ``` 延續函數的類型(參見 [§4.7](#4.7) )。 ### `lua_len` [-0, +1, _e_] ``` void lua_len (lua_State *L, int index); ``` 返回給定索引的值的長度。 它等價于 Lua 中的 '`#`' 操作符 (參見 [§3.4.7](#3.4.7))。 它有可能觸發 "length" 事件對應的元方法 (參見 [§2.4](#2.4) )。 結果壓棧。 ### `lua_load` [-0, +1, –] ``` int lua_load (lua_State *L, lua_Reader reader, void *data, const char *chunkname, const char *mode); ``` 加載一段 Lua 代碼塊,但不運行它。 如果沒有錯誤, `lua_load` 把一個編譯好的代碼塊作為一個 Lua 函數壓到棧頂。 否則,壓入錯誤消息。 `lua_load` 的返回值可以是: * **[`LUA_OK`](#pdf-LUA_OK):** 沒有錯誤; * **`LUA_ERRSYNTAX`:** 在預編譯時碰到語法錯誤; * **[`LUA_ERRMEM`](#pdf-LUA_ERRMEM):** 內存分配錯誤; * **[`LUA_ERRGCMM`](#pdf-LUA_ERRGCMM):** 在運行 `__gc` 元方法時出錯了。 (這個錯誤和代碼塊加載過程無關,它是由垃圾收集器引發的。) `lua_load` 函數使用一個用戶提供的 `reader` 函數來讀取代碼塊(參見 [`lua_Reader`](#lua_Reader) )。 `data` 參數會被傳入 `reader` 函數。 `chunkname` 這個參數可以賦予代碼塊一個名字, 這個名字被用于出錯信息和調試信息(參見 [§4.9](#4.9))。 `lua_load` 會自動檢測代碼塊是文本的還是二進制的, 然后做對應的加載操作(參見程序 `luac` )。 字符串 `mode` 的作用和函數 [`load`](#pdf-load) 一致。 它還可以是 `NULL` 等價于字符串 "`bt`"。 `lua_load` 的內部會使用棧, 因此 reader 函數必須永遠在每次返回時保留棧的原樣。 如果返回的函數有上值, 第一個上值會被設置為 保存在注冊表(參見 [§4.5](#4.5)) `LUA_RIDX_GLOBALS` 索引處的全局環境。 在加載主代碼塊時,這個上值是 `_ENV` 變量(參見 [§2.2](#2.2))。 其它上值均被初始化為 **nil**。 ### `lua_newstate` [-0, +0, –] ``` lua_State *lua_newstate (lua_Alloc f, void *ud); ``` 創建一個運行在新的獨立的狀態機中的線程。 如果無法創建線程或狀態機(由于內存有限)則返回 `NULL`。 參數 `f` 是一個分配器函數; Lua 將通過這個函數做狀態機內所有的內存分配操作。 第二個參數 `ud` ,這個指針將在每次調用分配器時被轉入。 ### `lua_newtable` [-0, +1, _e_] ``` void lua_newtable (lua_State *L); ``` 創建一張空表,并將其壓棧。 它等價于 `lua_createtable(L, 0, 0)` 。 ### `lua_newthread` [-0, +1, _e_] ``` lua_State *lua_newthread (lua_State *L); ``` 創建一條新線程,并將其壓棧, 并返回維護這個線程的 [`lua_State`](#lua_State) 指針。 這個函數返回的新線程共享原線程的全局環境, 但是它有獨立的運行棧。 沒有顯式的函數可以用來關閉或銷毀掉一個線程。 線程跟其它 Lua 對象一樣是垃圾收集的條目之一。 ### `lua_newuserdata` [-0, +1, _e_] ``` void *lua_newuserdata (lua_State *L, size_t size); ``` 這個函數分配一塊指定大小的內存塊, 把內存塊地址作為一個完全用戶數據壓棧, 并返回這個地址。 宿主程序可以隨意使用這塊內存。 ### `lua_next` [-1, +(2|0), _e_] ``` int lua_next (lua_State *L, int index); ``` 從棧頂彈出一個鍵, 然后把索引指定的表中的一個鍵值對壓棧 (彈出的鍵之后的 “下一” 對)。 如果表中以無更多元素, 那么 [`lua_next`](#lua_next) 將返回 0 (什么也不壓棧)。 典型的遍歷方法是這樣的: ``` /* 表放在索引 't' 處 */ lua_pushnil(L); /* 第一個鍵 */ while (lua_next(L, t) != 0) { /* 使用 '鍵' (在索引 -2 處) 和 '值' (在索引 -1 處)*/ printf("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); /* 移除 '值' ;保留 '鍵' 做下一次迭代 */ lua_pop(L, 1); } ``` 在遍歷一張表的時候, 不要直接對鍵調用 [`lua_tolstring`](#lua_tolstring) , 除非你知道這個鍵一定是一個字符串。 調用 [`lua_tolstring`](#lua_tolstring) 有可能改變給定索引位置的值; 這會對下一次調用 [`lua_next`](#lua_next) 造成影響。 關于迭代過程中修改被迭代的表的注意事項參見 [`next`](#pdf-next) 函數。 ### `lua_Number` ``` typedef double lua_Number; ``` Lua 中浮點數的類型。 Lua 中數字的類型。缺省是 double ,但是你可以改成 float 。 (參見 `luaconf.h` 中的 `LUA_REAL` 。) ### `lua_numbertointeger` ``` int lua_numbertointeger (lua_Number n, lua_Integer *p); ``` 將一個 Lua 浮點數轉換為一個 Lua 整數。 這個宏假設 `n` 有對應的整數值。 如果該值在 Lua 整數可表示范圍內, 就將其轉換為一個整數賦給 `*p`。 宏的結果是一個布爾量,表示轉換是否成功。 (注意、由于圓整關系,這個范圍測試不用此宏很難做對。) 該宏有可能對其參數做多次取值。 ### `lua_pcall` [-(nargs + 1), +(nresults|1), –] ``` int lua_pcall (lua_State *L, int nargs, int nresults, int msgh); ``` 以保護模式調用一個函數。 `nargs` 和 `nresults` 的含義與 [`lua_call`](#lua_call) 中的相同。 如果在調用過程中沒有發生錯誤, [`lua_pcall`](#lua_pcall) 的行為和 [`lua_call`](#lua_call) 完全一致。 但是,如果有錯誤發生的話, [`lua_pcall`](#lua_pcall) 會捕獲它, 然后把唯一的值(錯誤消息)壓棧,然后返回錯誤碼。 同 [`lua_call`](#lua_call) 一樣, [`lua_pcall`](#lua_pcall) 總是把函數本身和它的參數從棧上移除。 如果 `msgh` 是 0 , 返回在棧頂的錯誤消息就和原始錯誤消息完全一致。 否則, `msgh` 就被當成是 _錯誤處理函數_ 在棧上的索引位置。 (在當前的實現里,這個索引不能是偽索引。) 在發生運行時錯誤時, 這個函數會被調用而參數就是錯誤消息。 錯誤處理函數的返回值將被 [`lua_pcall`](#lua_pcall) 作為錯誤消息返回在堆棧上。 典型的用法中,錯誤處理函數被用來給錯誤消息加上更多的調試信息, 比如棧跟蹤信息。 這些信息在 [`lua_pcall`](#lua_pcall) 返回后, 由于棧已經展開,所以收集不到了。 [`lua_pcall`](#lua_pcall) 函數會返回下列常數 (定義在 `lua.h` 內)中的一個: * **`LUA_OK` (0):** 成功。 * **`LUA_ERRRUN`:** 運行時錯誤。 * **`LUA_ERRMEM`:** 內存分配錯誤。對于這種錯,Lua 不會調用錯誤處理函數。 * **`LUA_ERRERR`:** 在運行錯誤處理函數時發生的錯誤。 * **`LUA_ERRGCMM`:** 在運行 `__gc` 元方法時發生的錯誤。 (這個錯誤和被調用的函數無關。) ### `lua_pcallk` [-(nargs + 1), +(nresults|1), –] ``` int lua_pcallk (lua_State *L, int nargs, int nresults, int msgh, lua_KContext ctx, lua_KFunction k); ``` 這個函數的行為和 [`lua_pcall`](#lua_pcall) 完全一致,只不過它還允許被調用的函數讓出 (參見 [§4.7](#4.7))。 ### `lua_pop` [-n, +0, –] ``` void lua_pop (lua_State *L, int n); ``` 從棧中彈出 `n` 個元素。 ### `lua_pushboolean` [-0, +1, –] ``` void lua_pushboolean (lua_State *L, int b); ``` 把 `b` 作為一個布爾量壓棧。 ### `lua_pushcclosure` [-n, +1, _e_] ``` void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); ``` 把一個新的 C 閉包壓棧。 當創建了一個 C 函數后, 你可以給它關聯一些值, 這就是在創建一個 C 閉包(參見 [§4.4](#4.4)); 接下來無論函數何時被調用,這些值都可以被這個函數訪問到。 為了將一些值關聯到一個 C 函數上, 首先這些值需要先被壓入堆棧(如果有多個值,第一個先壓)。 接下來調用 [`lua_pushcclosure`](#lua_pushcclosure) 來創建出閉包并把這個 C 函數壓到棧上。 參數 `n` 告之函數有多少個值需要關聯到函數上。 [`lua_pushcclosure`](#lua_pushcclosure) 也會把這些值從棧上彈出。 `n` 的最大值是 255 。 當 `n` 為零時, 這個函數將創建出一個 _輕量 C 函數_, 它就是一個指向 C 函數的指針。 這種情況下,不可能拋出內存錯誤。 ### `lua_pushcfunction` [-0, +1, –] ``` void lua_pushcfunction (lua_State *L, lua_CFunction f); ``` 將一個 C 函數壓棧。 這個函數接收一個 C 函數指針, 并將一個類型為 `function` 的 Lua 值壓棧。 當這個棧頂的值被調用時,將觸發對應的 C 函數。 注冊到 Lua 中的任何函數都必須遵循正確的協議來接收參數和返回值 (參見 [`lua_CFunction`](#lua_CFunction) )。 `lua_pushcfunction` 是作為一個宏定義出現的: ``` #define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0) ``` ### `lua_pushfstring` [-0, +1, _e_] ``` const char *lua_pushfstring (lua_State *L, const char *fmt, ...); ``` 把一個格式化過的字符串壓棧, 然后返回這個字符串的指針。 它和 C 函數 `sprintf` 比較像, 不過有一些重要的區別: * 你不需要為結果分配空間: 其結果是一個 Lua 字符串,由 Lua 來關心其內存分配 (同時通過垃圾收集來釋放內存)。 * 這個轉換非常的受限。 不支持符號、寬度、精度。 轉換符只支持 '`%%`' (插入一個字符 '`%`'), '`%s`' (插入一個帶零終止符的字符串,沒有長度限制), '`%f`' (插入一個 [`lua_Number`](#lua_Number)), '`%L`' (插入一個 [`lua_Integer`](#lua_Integer)), '`%p`' (插入一個指針或是一個十六進制數), '`%d`' (插入一個 `int`), '`%c`' (插入一個用 `int` 表示的單字節字符),以及 '`%U`' (插入一個用 `long int` 表示的 UTF-8 字)。 ### `lua_pushglobaltable` [-0, +1, –] ``` void lua_pushglobaltable (lua_State *L); ``` 將全局環境壓棧。 ### `lua_pushinteger` [-0, +1, –] ``` void lua_pushinteger (lua_State *L, lua_Integer n); ``` 把值為 `n` 的整數壓棧。 ### `lua_pushlightuserdata` [-0, +1, –] ``` void lua_pushlightuserdata (lua_State *L, void *p); ``` 把一個輕量用戶數據壓棧。 用戶數據是保留在 Lua 中的 C 值。 _輕量用戶數據_ 表示一個指針 `void*`。 它是一個像數字一樣的值: 你不需要專門創建它,它也沒有獨立的元表,而且也不會被收集(因為從來不需要創建)。 只要表示的 C 地址相同,兩個輕量用戶數據就相等。 ### `lua_pushliteral` [-0, +1, _e_] ``` const char *lua_pushliteral (lua_State *L, const char *s); ``` 這個宏等價于 [`lua_pushlstring`](#lua_pushlstring), 區別僅在于只能在 `s` 是一個字面量時才能用它。 它會自動給出字符串的長度。 ### `lua_pushlstring` [-0, +1, _e_] ``` const char *lua_pushlstring (lua_State *L, const char *s, size_t len); ``` 把指針 `s` 指向的長度為 `len` 的字符串壓棧。 Lua 對這個字符串做一個內部副本(或是復用一個副本), 因此 `s` 處的內存在函數返回后,可以釋放掉或是立刻重用于其它用途。 字符串內可以是任意二進制數據,包括零字符。 返回內部副本的指針。 ### `lua_pushnil` [-0, +1, –] ``` void lua_pushnil (lua_State *L); ``` 將空值壓棧。 ### `lua_pushnumber` [-0, +1, –] ``` void lua_pushnumber (lua_State *L, lua_Number n); ``` 把一個值為 `n` 的浮點數壓棧。 ### `lua_pushstring` [-0, +1, _e_] ``` const char *lua_pushstring (lua_State *L, const char *s); ``` 將指針 s 指向的零結尾的字符串壓棧。 因此 `s` 處的內存在函數返回后,可以釋放掉或是立刻重用于其它用途。 返回內部副本的指針。 如果 `s` 為 `NULL`,將 **nil** 壓棧并返回 `NULL`。 ### `lua_pushthread` [-0, +1, –] ``` int lua_pushthread (lua_State *L); ``` 把 `L` 表示的線程壓棧。 如果這個線程是當前狀態機的主線程的話,返回 1 。 ### `lua_pushvalue` [-0, +1, –] ``` void lua_pushvalue (lua_State *L, int index); ``` 把棧上給定索引處的元素作一個副本壓棧。 ### `lua_pushvfstring` [-0, +1, _e_] ``` const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp); ``` 等價于 [`lua_pushfstring`](#lua_pushfstring) , 不過是用 `va_list` 接收參數,而不是用可變數量的實際參數。 ### `lua_rawequal` [-0, +0, –] ``` int lua_rawequal (lua_State *L, int index1, int index2); ``` 如果索引 `index1` 與索引 `index2` 處的值 本身相等(即不調用元方法),返回 1 。 否則返回 0 。 當任何一個索引無效時,也返回 0 。 ### `lua_rawget` [-1, +1, –] ``` int lua_rawget (lua_State *L, int index); ``` 類似于 [`lua_gettable`](#lua_gettable) , 但是作一次直接訪問(不觸發元方法)。 ### `lua_rawgeti` [-0, +1, –] ``` int lua_rawgeti (lua_State *L, int index, lua_Integer n); ``` 把 `t[n]` 的值壓棧, 這里的 `t` 是指給定索引處的表。 這是一次直接訪問;就是說,它不會觸發元方法。 返回入棧值的類型。 ### `lua_rawgetp` [-0, +1, –] ``` int lua_rawgetp (lua_State *L, int index, const void *p); ``` 把 `t[k]` 的值壓棧, 這里的 `t` 是指給定索引處的表, `k` 是指針 `p` 對應的輕量用戶數據。 這是一次直接訪問;就是說,它不會觸發元方法。 返回入棧值的類型。 ### `lua_rawlen` [-0, +0, –] ``` size_t lua_rawlen (lua_State *L, int index); ``` 返回給定索引處值的固有“長度”: 對于字符串,它指字符串的長度; 對于表;它指不觸發元方法的情況下取長度操作('`#`')應得到的值; 對于用戶數據,它指為該用戶數據分配的內存塊的大小; 對于其它值,它為 0 。 ### `lua_rawset` [-2, +0, _e_] ``` void lua_rawset (lua_State *L, int index); ``` 類似于 [`lua_settable`](#lua_settable) , 但是是做一次直接賦值(不觸發元方法)。 ### `lua_rawseti` [-1, +0, _e_] ``` void lua_rawseti (lua_State *L, int index, lua_Integer i); ``` 等價于 `t[i] = v` , 這里的 `t` 是指給定索引處的表, 而 `v` 是棧頂的值。 這個函數會將值彈出棧。 賦值是直接的;即不會觸發元方法。 ### `lua_rawsetp` [-1, +0, _e_] ``` void lua_rawsetp (lua_State *L, int index, const void *p); ``` 等價于 `t[k] = v` , 這里的 `t` 是指給定索引處的表, `k` 是指針 `p` 對應的輕量用戶數據。 而 `v` 是棧頂的值。 這個函數會將值彈出棧。 賦值是直接的;即不會觸發元方法。 ### `lua_Reader` ``` typedef const char * (*lua_Reader) (lua_State *L, void *data, size_t *size); ``` [`lua_load`](#lua_load) 用到的讀取器函數, 每次它需要一塊新的代碼塊的時候, [`lua_load`](#lua_load) 就調用讀取器, 每次都會傳入一個參數 `data` 。 讀取器需要返回含有新的代碼塊的一塊內存的指針, 并把 `size` 設為這塊內存的大小。 內存塊必須在下一次函數被調用之前一直存在。 讀取器可以通過返回 `NULL` 或設 `size` 為 0 來指示代碼塊結束。 讀取器可能返回多個塊,每個塊可以有任意的大于零的尺寸。 ### `lua_register` [-0, +0, _e_] ``` 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` [-1, +0, –] ``` void lua_remove (lua_State *L, int index); ``` 從給定有效索引處移除一個元素, 把這個索引之上的所有元素移下來填補上這個空隙。 不能用偽索引來調用這個函數,因為偽索引并不指向真實的棧上的位置。 ### `lua_replace` [-1, +0, –] ``` void lua_replace (lua_State *L, int index); ``` 把棧頂元素放置到給定位置而不移動其它元素 (因此覆蓋了那個位置處的值),然后將棧頂元素彈出。 ### `lua_resume` [-?, +?, –] ``` int lua_resume (lua_State *L, lua_State *from, int nargs); ``` 在給定線程中啟動或延續一條協程 。 要啟動一個協程的話, 你需要把主函數以及它需要的參數壓入線程棧; 然后調用 [`lua_resume`](#lua_resume) , 把 `nargs` 設為參數的個數。 這次調用會在協程掛起時或是結束運行后返回。 當函數返回時,堆棧中會有傳給 [`lua_yield`](#lua_yield) 的所有值, 或是主函數的所有返回值。 當協程讓出, [`lua_resume`](#lua_resume) 返回 [`LUA_YIELD`](#pdf-LUA_YIELD) , 若協程結束運行且沒有任何錯誤時,返回 0 。 如果有錯則返回錯誤代碼(參見 [`lua_pcall`](#lua_pcall) )。 在發生錯誤的情況下, 堆棧沒有展開, 因此你可以使用調試 API 來處理它。 錯誤消息放在棧頂在。 要延續一個協程, 你需要清除上次 [`lua_yield`](#lua_yield) 遺留下的所有結果, 你把需要傳給 `yield` 作結果的值壓棧, 然后調用 [`lua_resume`](#lua_resume) 。 參數 `from` 表示協程從哪個協程中來延續 `L` 的。 如果不存在這樣一個協程,這個參數可以是 `NULL` 。 ### `lua_rotate` [-0, +0, –] ``` void lua_rotate (lua_State *L, int idx, int n); ``` 把從 `idx` 開始到棧頂的元素輪轉 `n` 個位置。 對于 `n` 為正數時,輪轉方向是向棧頂的; 當 `n` 為負數時,向棧底方向輪轉 `-n` 個位置。 `n` 的絕對值不可以比參于輪轉的切片長度大。 ### `lua_setallocf` [-0, +0, –] ``` void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); ``` 把指定狀態機的分配器函數換成帶上用戶數據 `ud` 的 `f` 。 ### `lua_setfield` [-1, +0, _e_] ``` void lua_setfield (lua_State *L, int index, const char *k); ``` 做一個等價于 `t[k] = v` 的操作, 這里 `t` 是給出的索引處的值, 而 `v` 是棧頂的那個值。 這個函數將把這個值彈出棧。 跟在 Lua 中一樣,這個函數可能觸發一個 "newindex" 事件的元方法 (參見 [§2.4](#2.4))。 ### `lua_setglobal` [-1, +0, _e_] ``` void lua_setglobal (lua_State *L, const char *name); ``` 從堆棧上彈出一個值,并將其設為全局變量 `name` 的新值。 ### `lua_seti` [-1, +0, _e_] ``` void lua_seti (lua_State *L, int index, lua_Integer n); ``` 做一個等價于 `t[n] = v` 的操作, 這里 `t` 是給出的索引處的值, 而 `v` 是棧頂的那個值。 這個函數將把這個值彈出棧。 跟在 Lua 中一樣,這個函數可能觸發一個 "newindex" 事件的元方法 (參見 [§2.4](#2.4))。 ### `lua_setmetatable` [-1, +0, –] ``` void lua_setmetatable (lua_State *L, int index); ``` 把一張表彈出棧,并將其設為給定索引處的值的元表。 ### `lua_settable` [-2, +0, _e_] ``` void lua_settable (lua_State *L, int index); ``` 做一個等價于 `t[k] = v` 的操作, 這里 `t` 是給出的索引處的值, `v` 是棧頂的那個值, `k` 是棧頂之下的值。 這個函數會將鍵和值都彈出棧。 跟在 Lua 中一樣,這個函數可能觸發一個 "newindex" 事件的元方法 (參見 [§2.4](#2.4))。 ### `lua_settop` [-?, +?, –] ``` void lua_settop (lua_State *L, int index); ``` 參數允許傳入任何索引以及 0 。 它將把堆棧的棧頂設為這個索引。 如果新的棧頂比原來的大, 超出部分的新元素將被填為 **nil** 。 如果 `index` 為 0 , 把棧上所有元素移除。 ### `lua_setuservalue` [-1, +0, –] ``` void lua_setuservalue (lua_State *L, int index); ``` 從棧上彈出一個值并將其設為給定索引處用戶數據的關聯值。 ### `lua_State` ``` typedef struct lua_State lua_State; ``` 一個不透明的結構, 它指向一條線程并間接(通過該線程)引用了整個 Lua 解釋器的狀態。 Lua 庫是完全可重入的: 它沒有任何全局變量。 狀態機所有的信息都可以通過這個結構訪問到。 這個結構的指針必須作為第一個參數傳遞給每一個庫函數。 [`lua_newstate`](#lua_newstate) 是一個例外, 這個函數會從頭創建一個 Lua 狀態機。 ### `lua_status` [-0, +0, –] ``` int lua_status (lua_State *L); ``` 返回線程 `L` 的狀態。 正常的線程狀態是 0 ([`LUA_OK`](#pdf-LUA_OK))。 當線程用 [`lua_resume`](#lua_resume) 執行完畢并拋出了一個錯誤時, 狀態值是錯誤碼。 如果線程被掛起,狀態為 `LUA_YIELD` 。 你只能在狀態為 [`LUA_OK`](#pdf-LUA_OK) 的線程中調用函數。 你可以延續一個狀態為 [`LUA_OK`](#pdf-LUA_OK) 的線程 (用于開始新協程)或是狀態為 [`LUA_YIELD`](#pdf-LUA_YIELD) 的線程 (用于延續協程)。 ### `lua_stringtonumber` [-0, +1, –] ``` size_t lua_stringtonumber (lua_State *L, const char *s); ``` 將一個零結尾的字符串 `s` 轉換為一個數字, 將這個數字壓棧,并返回字符串的總長度(即長度加一)。 轉換的結果可能是整數也可能是浮點數, 這取決于 Lua 的轉換語法(參見 [§3.1](#3.1))。 這個字符串可以有前置和后置的空格以及符號。 如果字符串并非一個有效的數字,返回 0 并不把任何東西壓棧。 (注意,這個結果可以當成一個布爾量使用,為真即轉換成功。) ### `lua_toboolean` [-0, +0, –] ``` int lua_toboolean (lua_State *L, int index); ``` 把給定索引處的 Lua 值轉換為一個 C 中的布爾量( 0 或是 1 )。 和 Lua 中做的所有測試一樣, [`lua_toboolean`](#lua_toboolean) 會把任何不同于 **false** 和 **nil** 的值當作真返回; 否則就返回假。 (如果你想只接收真正的 boolean 值, 就需要使用 [`lua_isboolean`](#lua_isboolean) 來測試值的類型。) ### `lua_tocfunction` [-0, +0, –] ``` lua_CFunction lua_tocfunction (lua_State *L, int index); ``` 把給定索引處的 Lua 值轉換為一個 C 函數。 這個值必須是一個 C 函數; 如果不是就返回 `NULL` 。 ### `lua_tointeger` [-0, +0, –] ``` lua_Integer lua_tointeger (lua_State *L, int index); ``` 等價于調用 [`lua_tointegerx`](#lua_tointegerx), 其參數 `isnum` 為 `NULL`。 ### `lua_tointegerx` [-0, +0, –] ``` lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum); ``` 將給定索引處的 Lua 值轉換為帶符號的整數類型 [`lua_Integer`](#lua_Integer)。 這個 Lua 值必須是一個整數,或是一個可以被轉換為整數 (參見 [§3.4.3](#3.4.3))的數字或字符串; 否則,`lua_tointegerx` 返回 0 。 如果 `isnum` 不是 `NULL`, `*isnum` 會被設為操作是否成功。 ### `lua_tolstring` [-0, +0, _e_] ``` 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_next) 弄錯。) `lua_tolstring` 返回一個已對齊指針 指向 Lua 狀態機中的字符串。 這個字符串總能保證 ( C 要求的)最后一個字符為零 ('\0') , 而且它允許在字符串內包含多個這樣的零。 因為 Lua 中可能發生垃圾收集, 所以不保證 `lua_tolstring` 返回的指針, 在對應的值從堆棧中移除后依然有效。 ### `lua_tonumber` [-0, +0, –] ``` lua_Number lua_tonumber (lua_State *L, int index); ``` 等價于調用 [`lua_tonumberx`](#lua_tonumberx), 其參數 `isnum` 為 `NULL`。 ### `lua_tonumberx` [-0, +0, –] ``` lua_Number lua_tonumberx (lua_State *L, int index, int *isnum); ``` 把給定索引處的 Lua 值轉換為 [`lua_Number`](#lua_Number) 這樣一個 C 類型 (參見 lua_Number )。 這個 Lua 值必須是一個數字或是一個可轉換為數字的字符串 (參見 [§3.4.3](#3.4.3)); 否則, [`lua_tonumberx`](#lua_tonumberx) 返回 0 。 如果 `isnum` 不是 `NULL`, `*isnum` 會被設為操作是否成功。 ### `lua_topointer` [-0, +0, –] ``` const void *lua_topointer (lua_State *L, int index); ``` 把給定索引處的值轉換為一般的 C 指針 (`void*`) 。 這個值可以是一個用戶對象,表 ,線程或是一個函數; 否則, `lua_topointer` 返回 `NULL` 。 不同的對象有不同的指針。 不存在把指針再轉回原有類型的方法。 這個函數通常只用于調試信息。 ### `lua_tostring` [-0, +0, _e_] ``` const char *lua_tostring (lua_State *L, int index); ``` 等價于調用 [`lua_tolstring`](#lua_tolstring) , 其參數 `len` 為 `NULL` 。 ### `lua_tothread` [-0, +0, –] ``` lua_State *lua_tothread (lua_State *L, int index); ``` 把給定索引處的值轉換為一個 Lua 線程 (表示為 `lua_State*`)。 這個值必須是一個線程; 否則函數返回 `NULL`。 ### `lua_touserdata` [-0, +0, –] ``` void *lua_touserdata (lua_State *L, int index); ``` 如果給定索引處的值是一個完全用戶數據, 函數返回其內存塊的地址。 如果值是一個輕量用戶數據, 那么就返回它表示的指針。 否則,返回 `NULL` 。 ### `lua_type` [-0, +0, –] ``` int lua_type (lua_State *L, int index); ``` 返回給定有效索引處值的類型, 當索引無效(或無法訪問)時則返回 `LUA_TNONE`。 [`lua_type`](#lua_type) 返回的類型被編碼為一些個在 `lua.h` 中定義的常量: `LUA_TNIL`, `LUA_TNUMBER`, `LUA_TBOOLEAN`, `LUA_TSTRING`, `LUA_TTABLE`, `LUA_TFUNCTION`, `LUA_TUSERDATA`, `LUA_TTHREAD`, `LUA_TLIGHTUSERDATA`。 ### `lua_typename` [-0, +0, –] ``` const char *lua_typename (lua_State *L, int tp); ``` 返回 `tp` 表示的類型名, 這個 `tp` 必須是 [`lua_type`](#lua_type) 可能返回的值中之一。 ### `lua_Unsigned` ``` typedef ... lua_Unsigned; ``` [`lua_Integer`](#lua_Integer) 的無符號版本。 ### `lua_upvalueindex` [-0, +0, –] ``` int lua_upvalueindex (int i); ``` 返回當前運行的函數(參見 [§4.4](#4.4))的第 `i` 個上值的偽索引。 ### `lua_version` [-0, +0, _v_] ``` const lua_Number *lua_version (lua_State *L); ``` 返回保存在 Lua 內核中儲存的版本數字的地址。 當調用時傳入一個合法的 [`lua_State`](#lua_State) , 返回創建該狀態機時的版本地址。 如果用 `NULL` 調用, 返回調用者的版本地址。 ### `lua_Writer` ``` typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); ``` 被 [`lua_dump`](#lua_dump) 用到的寫入器函數。 每次 [`lua_dump`](#lua_dump) 產生了一段新的代碼塊, 它都會調用寫入器。 傳入要寫入的緩沖區 (`p`) 和它的尺寸 (`sz`) , 以及傳給 [`lua_dump`](#lua_dump) 的參數 `data` 。 寫入器會返回一個錯誤碼: 0 表示沒有錯誤; 別的值均表示一個錯誤, 并且會讓 [`lua_dump`](#lua_dump) 停止再次調用寫入器。 ### `lua_xmove` [-?, +?, –] ``` void lua_xmove (lua_State *from, lua_State *to, int n); ``` 交換同一個狀態機下不同線程中的值。 這個函數會從 `from` 的棧上彈出 `n` 個值, 然后把它們壓入 `to` 的棧上。 ### `lua_yield` [-?, +?, _e_] ``` int lua_yield (lua_State *L, int nresults); ``` 這個函數等價于調用 [`lua_yieldk`](#lua_yieldk), 不同的是不提供延續函數(參見 [§4.7](#4.7))。 因此,當線程被延續,線程會繼續運行調用 `lua_yield` 函數的函數。 ### `lua_yieldk` [-?, +?, _e_] ``` int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k); ``` 讓出協程(線程)。 當 C 函數調用了 [`lua_yieldk`](#lua_yieldk), 當前運行的協程會掛起, 啟動這個線程的 [`lua_resume`](#lua_resume) 調用返回。 參數 `nresults` 指棧上需返回給 [`lua_resume`](#lua_resume) 的返回值的個數。 當協程再次被延續時, Lua 調用延續函數 `k` 繼續運行被掛起(參見 [§4.7](#4.7))的 C 函數。 延續函數會從前一個函數中接收到相同的棧, 棧中的 `n` 個返回值被移除而壓入了從 [`lua_resume`](#lua_resume) 傳入的參數。 此外,延續函數還會收到傳給 [`lua_yieldk`](#lua_yieldk) 的參數 `ctx`。 通常,這個函數不會返回; 當協程一次次延續,將從延續函數繼續運行。 然而,有一個例外: 當這個函數從一個逐行運行的鉤子函數(參見 [§4.9](#4.9)) 中調用時,`lua_yieldk` 不可以提供延續函數。 (也就是類似 [`lua_yield`](#lua_yield) 的形式), 而此時,鉤子函數在調用完讓出后將立刻返回。 Lua 會使協程讓出,一旦協程再次被延續, 觸發鉤子的函數會繼續正常運行。 當一個線程處于未提供延續函數的 C 調用中,調用它會拋出一個錯誤。 從并非用延續方式(例如:主線程)啟動的線程中調用它也會這樣。 ## 4.9 – 調試接口 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 linedefined; /* (S) */ int lastlinedefined; /* (S) */ unsigned char nups; /* (u) 上值的數量 */ unsigned char nparams; /* (u) 參數的數量 */ char isvararg; /* (u) */ char istailcall; /* (t) */ char short_src[LUA_IDSIZE]; /* (S) */ /* 私有部分 */ _其它域_ } lua_Debug; ``` 這是一個攜帶有有關函數或活動記錄的各種信息的結構。 [`lua_getstack`](#lua_getstack) 只會填充結構的私有部分供后面使用。 調用 [`lua_getinfo`](#lua_getinfo) 可以在 [`lua_Debug`](#lua_Debug) 中填充那些可被使用的信息域。 下面對 [`lua_Debug`](#lua_Debug) 的各個域做一個說明: * **`source`:** 創建這個函數的代碼塊的名字。 如果 `source` 以 '`@`' 打頭, 指這個函數定義在一個文件中,而 '`@`' 之后的部分就是文件名。 若 `source` 以 '`=`' 打頭, 剩余的部分由用戶行為來決定如何表示源碼。 其它的情況下,這個函數定義在一個字符串中, 而 `source` 正是那個字符串。 * **`short_src`:** 一個“可打印版本”的 `source` ,用于出錯信息。 * **`linedefined`:** 函數定義開始處的行號。 * **`lastlinedefined`:** 函數定義結束處的行號。 * **`what`:** 如果函數是一個 Lua 函數,則為一個字符串 `"Lua"` ; 如果是一個 C 函數,則為 `"C"`; 如果它是一個代碼塊的主體部分,則為 `"main"`。 * **`currentline`:** 給定函數正在執行的那一行。 當提供不了行號信息的時候, `currentline` 被設為 -1 。 * **`name`:** 給定函數的一個合理的名字。 因為 Lua 中的函數是一等公民, 所以它們沒有固定的名字: 一些函數可能是全局復合變量的值, 另一些可能僅僅只是被保存在一張表的某個域中。 `lua_getinfo` 函數會檢查函數是怎樣被調用的, 以此來找到一個適合的名字。 如果它找不到名字, `name` 就被設置為 `NULL` 。 * **`namewhat`:** 用于解釋 `name` 域。 `namewhat` 的值可以是 `"global"`, `"local"`, `"method"`, `"field"`, `"upvalue"`, 或是 `""` (空串)。 這取決于函數怎樣被調用。 (Lua 用空串表示其它選項都不符合。) * **`istailcall`:** 如果函數以尾調用形式調用,這個值就為真。 在這種情況下,當層的調用者不在棧中。 * **`nups`:** 函數的上值個數。 * **`nparams`:** 函數固定形參個數 (對于 C 函數永遠是 0 )。 * **`isvararg`:** 如果函數是一個可變參數函數則為真 (對于 C 函數永遠為真)。 ### `lua_gethook` [-0, +0, –] ``` lua_Hook lua_gethook (lua_State *L); ``` 返回當前的鉤子函數。 ### `lua_gethookcount` [-0, +0, –] ``` int lua_gethookcount (lua_State *L); ``` 返回當前的鉤子計數。 ### `lua_gethookmask` [-0, +0, –] ``` int lua_gethookmask (lua_State *L); ``` 返回當前的鉤子掩碼。 ### `lua_getinfo` [-(0|1), +(0|1|2), _e_] ``` int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); ``` 返回一個指定的函數或函數調用的信息。 當用于取得一次函數調用的信息時, 參數 `ar` 必須是一個有效的活動的記錄。 這條記錄可以是前一次調用 [`lua_getstack`](#lua_getstack) 得到的, 或是一個鉤子 (參見 [`lua_Hook`](#lua_Hook) )得到的參數。 用于獲取一個函數的信息時, 可以把這個函數壓入堆棧, 然后把 `what` 字符串以字符 '`&gt;`' 起頭。 (這會讓 `lua_getinfo` 從棧頂上彈出函數。) 例如,想知道函數 `f` 是在哪一行定義的, 你可以使用下列代碼: ``` lua_Debug ar; lua_getglobal(L, "f"); /* 取得全局變量 'f' */ lua_getinfo(L, ">S", &ar); printf("%d\n", ar.linedefined); ``` `what` 字符串中的每個字符都篩選出結構 `ar` 結構中一些域用于填充, 或是把一個值壓入堆棧: * **'`n`':** 填充 `name` 及 `namewhat` 域; * **'`S`':** 填充 `source` , `short_src` , `linedefined` , `lastlinedefined` ,以及 `what` 域; * **'`l`':** 填充 `currentline` 域; * **'`t`':** 填充 `istailcall` 域; * **'`u`':** 填充 `nups`, `nparams`,及 `isvararg` 域; * **'`f`':** 把正在運行中指定層次處函數壓棧; * **'`L`':** 將一張表壓棧,這張表中的整數索引用于描述函數中哪些行是有效行。 (_有效行_指有實際代碼的行,即你可以置入斷點的行。 無效行包括空行和只有注釋的行。) 如果這個選項和選項 '`f`' 同時使用, 這張表在函數之后壓棧。 這個函數出錯會返回 0 (例如,`what` 中有一個無效選項)。 ### `lua_getlocal` [-0, +(0|1), –] ``` const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); ``` 從給定活動記錄或從一個函數中獲取一個局部變量的信息。 對于第一種情況, 參數 `ar` 必須是一個有效的活動的記錄。 這條記錄可以是前一次調用 [`lua_getstack`](#lua_getstack) 得到的, 或是一個鉤子 (參見 [`lua_Hook`](#lua_Hook) )的參數。 索引 `n` 用于選擇要檢閱哪個局部變量; 參見 [`debug.getlocal`](#pdf-debug.getlocal) 中關于變量的索引和名字的介紹。 [`lua_getlocal`](#lua_getlocal) 將變量的值壓棧,并返回其名字。 對于第二種情況,`ar` 必須填 `NULL` 。 需要探知的函數必須放在棧頂。 對于這種情況,只有 Lua 函數的形參是可見的 (沒有關于還有哪些活動變量的信息) 也不會有任何值壓棧。 當索引大于活動的局部變量的數量, 返回 `NULL` (無任何壓棧) ### `lua_getstack` [-0, +0, –] ``` int lua_getstack (lua_State *L, int level, lua_Debug *ar); ``` 獲取解釋器的運行時棧的信息。 這個函數用正在運行中的指定層次處函數的 _活動記錄_ 來填寫 [`lua_Debug`](#lua_Debug) 結構的一部分。 0 層表示當前運行的函數, _n+1_ 層的函數就是調用第 _n_ 層 (尾調用例外,它不算在棧層次中) 函數的那一個。 如果沒有錯誤, [`lua_getstack`](#lua_getstack) 返回 1 ; 當調用傳入的層次大于堆棧深度的時候,返回 0 。 ### `lua_getupvalue` [-0, +(0|1), –] ``` const char *lua_getupvalue (lua_State *L, int funcindex, int n); ``` 獲取一個閉包的上值信息。 (對于 Lua 函數,上值是函數需要使用的外部局部變量, 因此這些變量被包含在閉包中。) [`lua_getupvalue`](#lua_getupvalue) 獲取第 `n` 個上值, 把這個上值的值壓棧, 并且返回它的名字。 `funcindex` 指向閉包在棧上的位置。 ( 因為上值在整個函數中都有效,所以它們沒有特別的次序。 因此,它們以字母次序來編號。) 當索引號比上值數量大的時候, 返回 `NULL`(而且不會壓入任何東西)。 對于 C 函數,所有上值的名字都是空串 `""`。 ### `lua_Hook` ``` typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); ``` 用于調試的鉤子函數類型。 無論何時鉤子被調用,它的參數 `ar` 中的 `event` 域都被設為觸發鉤子的事件。 Lua 把這些事件定義為以下常量: `LUA_HOOKCALL`,`LUA_HOOKRET`, `LUA_HOOKTAILCALL`,`LUA_HOOKLINE`, `LUA_HOOKCOUNT`。 除此之外,對于 line 事件, `currentline` 域也被設置。 要想獲得 `ar` 中的其他域, 鉤子必須調用 [`lua_getinfo`](#lua_getinfo) 。 對于 call 事件,`event` 可以是 `LUA_HOOKCALL` 這個通常值, 或是 `LUA_HOOKTAILCALL` 表示尾調用; 后一種情況,沒有對應的返回事件。 當 Lua 運行在一個鉤子內部時, 它將屏蔽掉其它對鉤子的調用。 也就是說,如果一個鉤子函數內再調回 Lua 來執行一個函數或是一個代碼塊 , 這個執行操作不會觸發任何的鉤子。 鉤子函數不能有延續點, 即不能用一個非空的 `k` 調用 [`lua_yieldk`](#lua_yieldk), [`lua_pcallk`](#lua_pcallk),或 [`lua_callk`](#lua_callk)。 鉤子函數可以在滿足下列條件時讓出: 只有行計數事件可以讓出,且不能在讓出時傳出任何值; 從鉤子里讓出必須用 [`lua_yield`](#lua_yield) 來結束鉤子的運行,且 `nresults` 必須為零。 ### `lua_sethook` [-0, +0, –] ``` void lua_sethook (lua_State *L, lua_Hook f, int mask, int count); ``` 設置一個調試用鉤子函數。 參數 `f` 是鉤子函數。 `mask` 指定在哪些事件時會調用: 它由下列一組位常量構成 `LUA_MASKCALL`, `LUA_MASKRET`, `LUA_MASKLINE`, `LUA_MASKCOUNT`。 參數 `count` 只在掩碼中包含有 `LUA_MASKCOUNT` 才有意義。 對于每個事件,鉤子被調用的情況解釋如下: * **call hook:** 在解釋器調用一個函數時被調用。 鉤子將于 Lua 進入一個新函數后, 函數獲取參數前被調用。 * **return hook:** 在解釋器從一個函數中返回時調用。 鉤子將于 Lua 離開函數之前的那一刻被調用。 沒有標準方法來訪問被函數返回的那些值。 * **line hook:** 在解釋器準備開始執行新的一行代碼時, 或是跳轉到這行代碼中時(即使在同一行內跳轉)被調用。 (這個事件僅僅在 Lua 執行一個 Lua 函數時發生。) * **count hook:** 在解釋器每執行 `count` 條指令后被調用。 (這個事件僅僅在 Lua 執行一個 Lua 函數時發生。) 鉤子可以通過設置 `mask` 為零屏蔽。 ### `lua_setlocal` [-(0|1), +0, –] ``` const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); ``` 設置給定活動記錄中的局部變量的值。 參數 `ar` 與 `n` 和 [`lua_getlocal`](#lua_getlocal) 中的一樣 (參見 [`lua_getlocal`](#lua_getlocal) )。 [`lua_setlocal`](#lua_setlocal) 把棧頂的值賦給變量然后返回變量的名字。 它會將值從棧頂彈出。 當索引大于活動局部變量的數量時,返回 `NULL` (什么也不彈出)。 ### `lua_setupvalue` [-(0|1), +0, –] ``` const char *lua_setupvalue (lua_State *L, int funcindex, int n); ``` 設置閉包上值的值。 它把棧頂的值彈出并賦于上值并返回上值的名字。 參數 `funcindex` 與 `n` 和 [`lua_getupvalue`](#lua_getupvalue) 中的一樣 (參見 [`lua_getupvalue`](#lua_getupvalue) )。 當索引大于上值的數量時,返回 `NULL` (什么也不彈出)。 ### `lua_upvalueid` [-0, +0, –] ``` void *lua_upvalueid (lua_State *L, int funcindex, int n); ``` 返回索引 `funcindex` 處的閉包中 編號為 `n` 的上值的一個唯一標識符。 參數 `funcindex` 與 `n` 和 [`lua_getupvalue`](#lua_getupvalue) 中的一樣 (參見 [`lua_getupvalue`](#lua_getupvalue) )。 (但 `n` 不可以大于上值的數量)。 這些唯一標識符可用于檢測不同的閉包是否共享了相同的上值。 共享同一個上值的 Lua 閉包(即它們指的同一個外部局部變量) 會針對這個上值返回相同的標識。 ### `lua_upvaluejoin` [-0, +0, –] ``` void lua_upvaluejoin (lua_State *L, int funcindex1, int n1, int funcindex2, int n2); ``` 讓索引 `funcindex1` 處的 Lua 閉包的第 `n1` 個上值 引用索引 `funcindex2` 處的 Lua 閉包的第 `n2` 個上值。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看