首先咱們來說一下棧:
api
lua與c語言通信的主要方法是經過一個無所不在的虛擬棧。幾乎全部的api調用都會操做這個棧上的值:全部的數據交換,不管是lua到c語言或c語言到lua都是經過這個棧來完成。棧能夠解決lua與c語言之間存在的兩大差別,第一個差別時lua使用垃圾回收收集,而c語言要求顯示地釋放內存;第二種是lua使用動態類型,而c語言使用靜態類型。
函數
咱們來看一下c與lua之間是怎麼通信的:(假如c語言想知道lua中的money字符串的值)
lua
1.c想獲取lua中的money字符串的值,須要c把money房放到棧頂,以便lua能看到。
spa
2.lua從棧頂中獲取money,此時棧頂再次變爲空
指針
3.lua經過money這個字段在其全局表中進行查找
code
4.全局表返回money對應的值,假設爲10000
索引
5.lua把取得的10000放到棧頂
內存
6.c能夠從棧頂取得10000
rem
咱們來看一下棧的操做:
字符串
1.壓入棧:
對於每種能夠呈如今lua中的c類型,api都有一個對應的壓入函數,以下:
void lua_pushnil(lua_State *L); void lua_pushboolean(lua_State *L, int bool); void lua_pushnumber(lua_State *L, lua_Number n); void lua_pushinteger(lua_State *L, lua_Integer n); void lua_pushlstring(lua_State *L, const char *s, size_t len); void lua_pushstring(lua_State *L, const char *s);
2.查詢元素:
api使用索引來訪問棧中的元素。第一個壓入棧中的元素索引爲1,第二個壓入的元素索引爲2,以此類推,直到棧頂。我麼也能夠用棧頂做爲參考物,使用負數來訪問棧中的元素。此時-1表示棧頂元素,-2表示棧頂下面的元素,以此類推。
爲了檢查一個元素是否爲特定的類型,api提供了一系列的函數lua_is*,其中*能夠是任意lua類型。這些函數有lua_number、lua_isstring和lua_istable等,原型以下:
int lua_is*(lua_State *L, int index);
3.取值:
咱們通常使用lua_to*函數從棧中獲取一個值,以下:
lua_Number lua_tonumber (lua_State *L, int idx); lua_Integer lua_tointeger (lua_State *L, int idx); int lua_toboolean (lua_State *L, int idx); const char *lua_tolstring (lua_State *L, int idx, size_t *len); size_t lua_objlen (lua_State *L, int idx); lua_CFunction lua_tocfunction (lua_State *L, int idx); void *lua_touserdata (lua_State *L, int idx); lua_State *lua_tothread (lua_State *L, int idx); const void *lua_topointer (lua_State *L, int idx);
若是指定的元素不具備正確的類型,調用這些函數也不會有問題。在這種狀況下,lua_toboolean、lua_tonumber、lua_tointeger和lua_objlen會返回0,而其它函數會返回NULL。lua_tolstring函數會返回一個指向內部字符串副本的指針,並將字符串的長度存入最後一個參數len中。這個內部副本不能修改,返回類型中的const也說明了這點。Lua保證只要這個對應的字符串還在棧中,那麼這個指針就是有效的。當Lua調用的一個C函數返回時,Lua就會清空它的棧。
棧的其它操做:
--返回棧中元素的個數,也能夠說是棧頂元素的索引 int lua_gettop (lua_State *L); --將棧頂設置爲一個指定的位置,即修改棧中元素的數量,若是以前的棧頂比新設置的更高,那麼高出來的這些元素會被丟棄--;反之,會向棧中壓入nil來補足大小.lua_settop(L, 0);表示清空棧 void lua_settop (lua_State *L, int idx); --將指定索引上值得副本壓入棧 void lua_pushvalue (lua_State *L, int idx); --刪除指定索引上的元素,並將該位置之上的全部元素下移以填補空缺 void lua_remove (lua_State *L, int idx); --上移指定位置之上的全部元素以開闢一個槽空間,而後將棧頂元素移到該位置 void lua_insert (lua_State *L, int idx); --彈出棧頂的值,並將該值設置到指定索引上,但它不會移動任何東西,只是替換了指定索引的值 void lua_replace (lua_State *L, int idx);