lua中得棧

若是你看了LUA的文檔,那麼就應該很清楚LUA與C交互數據時都是用到LUA中所謂的stack。那麼當我調用lua_open函數以後棧是什麼樣的呢?空的(luaopen_base等會往棧上加進一些東西)。那麼至於如何操做棧上的數據,我想官方文檔上已經說得很清楚了,不過最初我對於棧的順序有一些迷糊,因此就說說這個。如今假如我有以下的一段代碼: api

代碼:
lua_State* L = lua_open();
lua_pushnumber( L, 211 );
lua_pushnumber( L, 2222 );
lua_newtable( L );
lua_close( L );



那麼當執行完lua_newtable以後棧上有三個元素,大體就是這樣: 

211 
222 
table 

如今211是第一個元素,index爲1,不過LUA也能夠用負數來表示,那麼如今他是多少? 

index -index value 
1 -3 211 
2 -2 222 
3 -1 table 

嗯,很簡單,再看看若是咱們要設置一個TABLE的值怎麼作?文檔中說用lua_settable或是lua_rawset(這二者有什麼區別應該和這裏說的無關),它們參數意義、以及準備工做都同樣,-1是值,-2是鍵值 
lua_settable( lua_state*, int ) 
第一個參數是要操做的腳本環境,第二個則是要操做的表在棧上的位置 
通常的寫法多是這樣 函數

代碼:
// 代碼A
lua_getglobal( L, "myTable" );   // 獲取要設置值的table
lua_pushstring( L, "hp" );         // "hp"在棧上的位置爲-1
lua_pushnumber( L, 211 );          // "hp"在棧上的位置變爲-2,而211則是-1
lua_settable( L, -3 );               // 值被正確的設置到全局變量(表)的myTable中


若是我是想把hp這個值設置到全局表中呢?通常經過調用lua_setglobal宏 lua

代碼:
lua_pushnumber( L, 211 );
lua_setglobal( L, "hp" );


就這麼簡單,不過咱們來看看lua_setglobal這個宏 spa

代碼:
#define lua_setglobal(L,s)    /
   (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX))


這麼看來實際上咱們上面的代碼被替換成了 code

代碼:
lua_pushnumber( L, 211 );
lua_pushstring( L, "hp" );
lua_insert( L, -2 );         // 這一步看上去或許比較詭異,其實是把-1的值放到lua_insert的第二個參數所指的位置,而後這個位置後面的參數往上移
                               //這裏實際上最終結果就是-1和-2對調,但從邏輯上並非對調
lua_settable( L, LUA_GLOBALSINDEX );         // 這裏爲何不用lua_rawset?我認爲是有緣由的^@^



將上面的代碼與代碼A結合起來看,在lua_settable時index值不一樣,而它作的工做是若是發現index是LUA_GLOBALSINDEX 那麼就取出全局表(還有一個LUA_REGISTERINDEX,相似),不然從stack上取元素,固然,這個棧位置取出的不是一個table就會失敗。因此代碼A中指定的是-3是剛從全局表中取出的myTable表(這裏假設他是一個table),上面的代碼片斷則是取出的全局表。因此lua_settable的index是什麼值均可以,只要它指向的是一個table 

實際上lua中與c的接口也就主要在棧的操做上,基本上你在寫一個lua與C結合的程序時你最最須要作的工做就是明白你當前棧上有什麼元素以及它們的位置。我通常會在紙上畫出他們的位置,若是你熟了,對於幾句在一塊兒有關聯的lua調用則能夠很快的看出棧的變化。好比lua_gettable/lua_rawget 接口

代碼:
lua_pushstring( L, "hp" );
lua_gettable( L, LUA_GLOBALSINDEX );


只看第一句,棧頂是一個字符串,但兩句放在一塊兒,最終棧頂是一個全局表上一個名爲hp的實際值 文檔

代碼:
lua_pushstring( L, "hp" );
lua_pushnumber( L, 211 );
lua_settable( L, LUA_GLOBALSINDEX );


不管第二句pushnumber仍是pushvalue,pushstring什麼的,最終這三句執行以後對於棧來講是沒有任何變化的,由於lua_settable/lua_rawset會移走-1和-2 

總之,對於棧的變化,在看一個函數的文檔時先看它參數又須要棧上那些位置的元素並正確設置棧上的值,看清楚他會取棧上那些位置的元素做爲這個lua api調用的使用併爲之把正確的值放到棧上,最後注意函數完成以後會清除/移走那些位置的元素,我想應該就沒什麼問題了字符串

相關文章
相關標籤/搜索