標籤:
Lua與C是通過棧進行交換資料的,這個棧與我們在資料結構中所說的棧類似,遵循LIFO規則。下面是從官方文檔上截取的關於棧操作的 C API,對其進行分類整理了。
1. 壓入元素:
void lua_pushnil (lua_State *L);void lua_pushboolean(lua_State *L, int bool);void lua_pushnumber(lua_State *L, double n);void lua_pushinteger (lua_State *L, lua_Integer n);void lua_pushstring (lua_State *L, const char *s);const char *lua_pushfstring (lua_State *L, const char *fmt, ...);void lua_pushlstring (lua_State *L, const char *s, size_t len);const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp);void lua_pushcfunction (lua_State *L, lua_CFunction f);int lua_pushthread (lua_State *L);void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);void lua_pushlightuserdata (lua_State *L, void *p);
2. 擷取棧中元素:
在棧中第一個元素的索引為1, 下一個元素為2, 依次類推。我們也可以用棧頂作為參照來存取元素,利用負索引,在這種情況下,-1表示棧頂元素的索引,-2表示倒數第二個元素。
lua提供了如下函數來判斷元素類型: lua_is*
int lua_is*(lua_State *L, int index);int lua_type (lua_State *L, int index);
The types returned by lua_type are coded by the following constants defined in lua.h: LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA.
為了從棧中擷取值,使用lua_to...函數:
int lua_toboolean (lua_State *L, int index);lua_Integer lua_tointeger (lua_State *L, int index);lua_Number lua_tonumber (lua_State *L, int index);const char *lua_tostring (lua_State *L, int index);const char *lua_tolstring (lua_State *L, int index, size_t *len);lua_State *lua_tothread (lua_State *L, int index);void *lua_touserdata (lua_State *L, int index);
lua為了方便檢查元素類型並擷取元素的值,提供了luaL_check*函數,以及luaL_opt*函數。如果不滿足對應的類型,則 throw an error。
int luaL_checkint (lua_State *L, int narg);Checks whether the function argument narg is a number and returns this number cast to an int.
lua_Number luaL_checknumber (lua_State *L, int narg);Checks whether the function argument narg is a number and returns this number.
const char *luaL_checklstring (lua_State *L, int narg, size_t *l); Checks whether the function argument narg is a string and returns this string; if l is not NULL fills *l with the string‘s length.
void *luaL_checkudata (lua_State *L, int narg, const char *tname);Checks whether the function argument narg is a userdata of the type tname
int luaL_optint (lua_State *L, int narg, int d); If the function argument narg is a number, returns this number cast to an int. If this argument is absent or is nil, returns d. Otherwise, raises an error.
const char *luaL_optlstring (lua_State *L, int narg, const char *d, size_t *l); If the function argument narg is a string, returns this string. If this argument is absent or is nil, returns d. Otherwise, raises an error. If l is not NULL, fills the position *l with the results‘s length.
const char *luaL_optstring (lua_State *L, int narg, const char *d); If the function argument narg is a string, returns this string. If this argument is absent or is nil, returns d. Otherwise, raises an error.
3. 其他的棧操作:
int lua_gettop (lua_State *L); Returns the index of the top element in the stack. Because indices start at 1, this result is equal to the number of elements in the stack (and so 0 means an empty stack).
void lua_settop (lua_State *L, int index); Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed.
void lua_pushvalue (lua_State *L, int index);Pushes a copy of the element at the given valid index onto the stack.
void lua_remove (lua_State *L, int index); Removes the element at the given valid index, shifting down the elements above this index to fill the gap. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.
void lua_insert (lua_State *L, int index); Moves the top element into the given valid index, shifting up the elements above this index to open space. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.
void lua_replace (lua_State *L, int index); Moves the top element into the given position (and pops it), without shifting any element (therefore replacing the value at the given position).
void lua_pop (lua_State *L, int n);Pops n elements from the stack.
4. C API錯誤處理:
當我們向Lua添加C函數時,如果C函數中發生錯誤,可以使用luaL_error函數,它會清理所有在Lua中需要被清理的,然後和錯誤資訊一起回到最初的執行lua_pcall的地方。
int luaL_error (lua_State *L, const char *fmt, ...); Raises an error. The error message format is given by fmt plus any extra arguments, following the same rules of lua_pushfstring. It also adds at the beginning of the message the file name and the line number where the error occurred, if this information is available.This function never returns, but it is an idiom to use it in C functions as return luaL_error(args).
5. Table的操作:
1) 在棧上建立一個新的table
void lua_createtable (lua_State *L, int narr, int nrec); Creates a new empty table and pushes it onto the stack. The new table has space pre-allocated for narr array elements and nrec non-array elements. This pre-allocation is useful when you know exactly how many elements the table will have. Otherwise you can use the function lua_newtable. void lua_newtable (lua_State *L); Creates a new empty table and pushes it onto the stack. It is equivalent to lua_createtable(L, 0, 0).
2) 讀取Lua代碼中已有的table:
對於已經存在於lua _G table中的成員,可以用如下方法擷取:
void lua_getglobal (lua_State *L, const char *name);Pushes onto the stack the value of the global name. It is defined as a macro: #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s)
此函數返回後,對應的成員位於棧頂處。
3) 讀取table中鍵為key的元素
void lua_getfield (lua_State *L, int index, const char *k); Pushes onto the stack the value t[k], where t is the value at the given valid index. As in Lua, this function may trigger a metamethod for the "index" event
4) 設定table中鍵為key的元素值
void lua_setfield (lua_State *L, int index, const char *k); Does the equivalent to t[k] = v, where t is the value at the given valid index and v is the value at the top of the stack. This function pops the value from the stack. As in Lua, this function may trigger a metamethod for the "newindex" event
調用這個方法前,需要先將value壓入棧頂。lua_push*
5) 讀取數組中索引為key的元素:
void lua_rawgeti (lua_State *L, int index, int n); Pushes onto the stack the value t[n], where t is the value at the given valid index. The access is raw; that is, it does not invoke metamethods.
6) 設定數組中索引為key的元素值:
void lua_rawseti (lua_State *L, int index, int n); Does the equivalent of t[n] = v, where t is the value at the given valid index and v is the value at the top of the stack. This function pops the value from the stack. The assignment is raw; that is, it does not invoke metamethods.
調用這個方法前,也是需要先將value壓入棧頂,lua_push*
7) 擷取table中元素的個數:
size_t lua_objlen (lua_State *L, int index); Returns the "length" of the value at the given acceptable index: for strings, this is the string length; for tables, this is the result of the length operator (‘#‘); for userdata, this is the size of the block of memory allocated for the userdata; for other values, it is 0.
6. 查看棧
在<programing in lua>一書中,提供了stack_dump函數,用於查看當前的棧中所有元素,現將其源碼貼出:
void stack_dump(lua_State *L){int i;int top = lua_gettop(L);printf("Stack has %d elements:\n\t", top);for(i = 1; i <= top; ++i){int type = lua_type(L, i);switch(type){case LUA_TSTRING: // stringsprintf("‘%s‘", lua_tostring(L, i));break;case LUA_TBOOLEAN: // booleansprintf(lua_toboolean(L, i) ? "true" : "false");break;case LUA_TNUMBER: // numbersprintf("%g", lua_tonumber(L, i));break;default: // other valuesprintf("%s", lua_typename(L, i));break;}printf("\t");}printf("\n");}
6. lua-epoll的簡單分析:
我剛開始學習的時候,看了上面這麼多API,感覺還不怎麼熟練,所以就找了一個簡單的開原始碼來學習。
源碼地址: https://github.com/Hevienz/lua-epoll
README.md檔案中有說明如何使用該模組,具體的分析見下一篇文章。
lua c API