LUA解譯器的整個State如全域變數、堆棧等都儲存在一個結構類型為Lua_State動態分配的對象裡.指向這一對象的指標必須作為第一個參數傳遞給所有串連庫的API.在調用所有的API函數之前,你必須先用lua_open以產生一個State.
lua_State* lua_open(void)
通過調用lua_close來釋放一個通過lua_open產生的state:
void lua_close (lua_State *L)
銷毀給定的Lua_State中的所有對象並釋放state所佔用的動態記憶體
LUA使用虛擬堆棧機制和C程式互相傳值,所有的堆棧中的元素都可以看作一個LUA值如Nil,Number,String等
int lua_gettop(lua_State *L) //取得棧頂元素的索引.因為索引從1開始計數,所以lua_gettop的傳回值也就是這個堆棧的元素個數
把堆棧的尺寸擴大到可以容納Top+Extra個元素
int lua_checkstack (lua_State *L, ine extra)
任何時候Lua調用C,都可以保證最少有LUA_MINSTACK個堆棧位置是可用
把堆棧的棧頂索引設定為指定的數值
void lua_settop(lua_State* L, int index)
用於把從棧頂開始的n個元素刪除
#define lua_pop(L,n) lua_settop(L,-(n)-1)
將棧上指定索引處的值拷貝到棧頂
void lua_pushvalue(lua_State* L, int index)
刪除給定索引的元素並移動相應的元素
void lua_remove(lua_State* L, int index)
在給定索引處插入相應的元素同時溢出棧頂元素
void lua_insert(lua_State* L, int index)
用棧頂元素去替換棧上指定索引處的元素
void lua_replace(lua_State* L, int index)
檢測堆棧元素的資料類型可以使用如下函數
int lua_type (lua_State *L, int index) //返回堆棧元素的實值型別 int lua_isnil (lua_State *L, int index) int lua_isboolean (lua_State *L, int index) int lua_isnumber (lua_State *L, int index) int lua_isstring (lua_State *L, int index) int lua_istable (lua_State *L, int index) int lua_isfunction (lua_State *L, int index) int lua_iscfunction (lua_State *L, int index) int lua_isuserdata (lua_State *L, int index) int lua_islightuserdata(lua_State *L, int index)
比較堆棧中的兩個值 的大小的函數
int lua_equal (lua_State *L, int index1, int index2)int lua_rawequal(lua_State *L, int index1, int index2)int lua_lessthan(lua_State *L, int index1, int index2)
把堆棧中的值轉換為指定的C類型的相關函數
int lua_toboolean (lua_State *L, int index)lua_Number lua_tonumber (lua_State *L, int index)const char* lua_tostring (lua_State *L, int index)size_t lua_strlen (lua_State *L, int index)lua_CFunction lua_tocfunction(lua_State *L, int index)void *lua_touserdata (lua_State *L, int index)lua_State *lua_tothread (lua_State *L, int index)void *lua_topointer (lua_State *L, int index)
下列API能將C值壓入堆棧
void lua_pushboolean (lua_State *L, int b)void lua_pushnumber (lua_State *L, lua_Number n)void lua_pushlstring (lua_State *L, const char *s, size_t len)void lua_pushstring (lua_State *L, const char *s)void lua_pushnil (lua_State *L)void lua_pushcfunction (lua_State *L, lua_CFunction f)void lua_pushlightuserdata(lua_State *L, void *p)
格式化字串
const char *lua_pushfstring (lua_State *L, const char *fmt, ...)const char *lua_pushvfstring(lua_State *L, const char *fmt, va_list argp)
void lua_getfield(lua_State *L, int index, const char *k)//擷取棧上index索引指定的表上鍵為k的元素將之壓到棧頂
void lua_setfield (lua_State *L, int index, const char *k)//將棧上Index索引指定的表上鍵為k的元素值置為棧頂元素值
void lua_gettable (lua_State *L, int index)//擷取棧上index索引指定的表上鍵為棧頂元素值的元素將之壓到棧頂
void lua_settable (lua_State *L, int index)//將棧上index索引指定的表上鍵為棧頂開始第二個元素值的元素值置為棧頂元素值
void lua_rawgeti(lua_State *L, int index, int n)//擷取棧上index索引指定的表上下標為n的元素將之壓到棧頂
local TableA = {1,2,3,4,5};size_t nNum = lua_objlen(L,index);//index變數為TableA元素在棧上的索引for(unsigned int ix=1; ix <= nNum; ++ix){ lua_rawgeti(L,index,ix); int value = lua_tointeger(L,-1); lua_pop(L,1); }
local TableB = {x = "X", y="Y"} lua_getfiled(L,index,"X")//index變數為TableB元素在棧上的索引 const char* X = lua_tostring(L,-1) lua_pop(L,1); lua_getfiled(L,index,"y"); const char* Y = lua_tostring(L,-1); lua_pop(L,1);
lua registry是一個全域的Table,它只能被C代碼訪問,通常可以用它來儲存需要在幾個模組中共用的資料.lua registry總是位於一個虛擬索引值LUA_REGISTRYINDEX之上.
int ref = luaL_ref(L,LUA_REGISTRYINDEX)//將棧頂元素存入lua registry中並返回在lua registry中的索引
lua_rawgeti(L,LUA_REGISTRYINDEX, ref)//擷取lua registry 上索引為ref的元素壓入棧頂
luaL_unref(L, LUA_REGISTYRINDEX,ref)//當不需要繼續在lua registry中保留元素時,傳入索引ref將之從lua registry上移出,以避免資源泄漏
維護棧大小
int top = lua_gettop(L);lua_settop(L, top);
lua stack上可以容納的元素是有限的,而且會佔用資源,通常以成對的 lua_gettop 和 lua_settop調用來維護棧大小,保證其間的操作在棧上分配的局部對象不會在棧上保留,特別是在調用lua call執行了lua函數並有返回但忽略傳回值時.
調用lua函數
XL_LRT_API long __stdcall XLLRT_LuaCall(lua_State* luaState,int args,int results,const wchar_t* contextInfo);
調用lua函數,args指定傳入參數數量,棧頂為最後一個參數,向棧底方向棧上的元素順次為倒數第二參數直到第一個參數,第一個參數之前為要調用的函數對象.調用完成之後,將函數對象極其之後的所有元素從棧上彈出,如果results指定為LUA_MULTRET將函數對象的所有傳回值壓入棧上,否則壓入results個傳回值;contextInfo字串指定上下文資訊,在調用的lua函數出現指令碼錯誤時的回調中用做標識.在Bolt裡用要求用XLLuaRuntime模組的XLLRT_LuaCall調用代替lua_*call類函數.如lua
函數func,原型為 string,integer func(integer, string) , 在C中調用之:(index變數為func函數對象在棧上的索引,L為所在lua_State指標)
int top = lua_gettop(L); lua_pushvalue(L,index);//(index變數為func函數對象在棧上的索引 lua_pushinteger(L,1);lua_pushstring(L,"test");long result = XLLRT_LuaCall(L,2,2,L"for test"); if(result == 0){ const char* ret1 = lua_tostring(L,-2); int ret2 = lua_tointeger(L,-1); }lua_settop(L,top);
等效於在lua中調用func ret1, ret2 = func(1,"test").需要注意的是XLLRT_LuaCall的傳回值,當為0時說明調用的lua函數被正確執行,否則說明lua函數執行中斷,一般是出現了指令碼錯誤,此時lua棧上是不會有func函數執行之後的傳回值的,不能取傳回值進行操作,或者繼續執行依賴於func成功執行的任何操作.
函數lua_getglobal()是用來將lua指令檔中的全域變數壓入到堆棧中,這個函數有兩個參數,第一個參數是lua的狀態機器(用於儲存資料),
第二個參數是你想擷取的全域變數的名稱標識符.
void lua_setglobal (lua_State *L, const char *name); #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s)
從堆棧上彈出一個值,並將其設到全域變數 name 中.它由一個宏定義出來
void lua_newtable (lua_State *L); 《=》lua_createtable(L,0,0) 建立一個空Table ,並將之壓入堆棧
void lua_settable (lua_State *L, int index);
作一個等價於 t[k] = v 的操作,這裡t是一個給定有效索引 index 處的值,v 指棧頂的值,而 k 是棧頂之下的那個值.這個函數會把鍵和值都從堆棧中彈出.
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.