第一版是針對 Lua 5.0 編寫的。雖然大部分內容仍然適用於後續版本,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買書籍,您也能 贊助 Lua 專案。
![]() |
用 Lua 程式設計 | ![]() |
第四部分。C API 第 24 章。C API 概觀 |
我們將從一個應用程式範例開始這個概觀:一個獨立的 Lua 解譯器。我們可以撰寫一個原始的獨立解譯器,如下所示
警告:此程式碼適用於 Lua 5.0。要在 Lua 5.1 中執行,您必須將五個呼叫 luaopen_*(L)
變更為單一呼叫 luaL_openlibs(L)
。
#include <stdio.h> #include <string.h> #include <lua.h> #include <lauxlib.h> #include <lualib.h> int main (void) { char buff[256]; int error; lua_State *L = lua_open(); /* opens Lua */ luaopen_base(L); /* opens the basic library */ luaopen_table(L); /* opens the table library */ luaopen_io(L); /* opens the I/O library */ luaopen_string(L); /* opens the string lib. */ luaopen_math(L); /* opens the math lib. */ while (fgets(buff, sizeof(buff), stdin) != NULL) { error = luaL_loadbuffer(L, buff, strlen(buff), "line") || lua_pcall(L, 0, 0, 0); if (error) { fprintf(stderr, "%s", lua_tostring(L, -1)); lua_pop(L, 1); /* pop error message from the stack */ } } lua_close(L); return 0; }標頭檔
lua.h
定義 Lua 提供的基本函式。其中包括建立新的 Lua 環境(例如 lua_open
)、呼叫 Lua 函式(例如 lua_pcall
)、讀取和寫入 Lua 環境中的全域變數、註冊新的函式以供 Lua 呼叫,等等。在 lua.h
中定義的所有內容都帶有 lua_
前綴。
標頭檔 lauxlib.h
定義輔助函式庫(auxlib)提供的函式。其所有定義都以 luaL_
開頭(例如 luaL_loadbuffer
)。輔助函式庫使用 lua.h
提供的基本 API 提供較高的抽象層級;所有 Lua 標準函式庫都使用 auxlib。基本 API 追求精簡和正交性,而 auxlib 則追求實用性以執行常見任務。當然,您的程式也可以非常容易地建立其他它需要的抽象。請記住,auxlib 無法存取 Lua 的內部。它透過官方基本 API 完成所有工作。
Lua 函式庫完全沒有定義任何全域變數。它將所有狀態保留在動態結構 lua_State
中,而且指向此結構的指標會傳遞為 Lua 內部所有函式的引數。此實作讓 Lua 可重新進入,並準備好在多執行緒程式碼中使用。
lua_open
函數會建立一個新的環境(或稱狀態)。當 lua_open
建立一個新的環境時,這個環境不包含任何預先定義的函數,甚至連 print
都沒有。為了讓 Lua 保持精簡,所有標準函式庫都以獨立套件的形式提供,因此您不必在不需要時使用它們。標頭檔 lualib.h
定義了開啟函式庫的函數。例如,呼叫 luaopen_io
會建立 io
表格,並在其中註冊 I/O 函數(io.read
、io.write
等)。
在建立一個狀態並使用標準函式庫填充它之後,就可以開始詮釋使用者的輸入了。對於使用者輸入的每一行,程式會先呼叫 luaL_loadbuffer
來編譯程式碼。如果沒有錯誤,呼叫會傳回零並將產生的區塊推入堆疊中。(請記住,我們將在下一個區段詳細討論這個「神奇」的堆疊。)然後,程式會呼叫 lua_pcall
,它會從堆疊中彈出區塊並在受保護模式中執行它。與 luaL_loadbuffer
相同,如果沒有錯誤,lua_pcall
會傳回零。如果發生錯誤,這兩個函數都會在堆疊中推入一個錯誤訊息;我們可以使用 lua_tostring
取得這個訊息,並在列印它之後使用 lua_pop
將它從堆疊中移除。
請注意,如果發生錯誤,這個程式只會將錯誤訊息列印到標準錯誤串流中。真正的錯誤處理在 C 中可能相當複雜,而且處理方式會根據應用程式的性質而有所不同。Lua 核心從來不會直接將任何內容寫入任何輸出串流中;它會透過傳回錯誤碼和錯誤訊息來表示錯誤。每個應用程式都可以用最適合其需求的方式來處理這些訊號。為了簡化我們的討論,我們現在假設一個簡單的錯誤處理常式,如下所示,它會列印錯誤訊息、關閉 Lua 狀態,並退出整個應用程式
#include <stdarg.h> #include <stdio.h> #include <stdlib.h> void error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); vfprintf(stderr, argp); va_end(argp); lua_close(L); exit(EXIT_FAILURE); }稍後我們將在應用程式程式碼中進一步討論錯誤處理。
由於您可以將 Lua 編譯為 C 和 C++ 程式碼,因此 lua.h
不包含在其他幾個 C 函式庫中存在的這個典型調整程式碼
#ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus } #endif因此,如果您已將 Lua 編譯為 C 程式碼(最常見的情況)並在 C++ 中使用它,您必須如下所示包含
lua.h
extern "C" { #include <lua.h> }一個常見的技巧是建立一個包含上述程式碼的標頭檔
lua.hpp
,並在您的 C++ 程式中包含這個新檔案。
版權所有 © 2003–2004 Roberto Ierusalimschy。保留所有權利。 | ![]() |