生活随笔
收集整理的這篇文章主要介紹了
Lua 和 C 交互中虚拟栈的操作和遍历
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
int lua_pcall(lua_State *L, int nargs, int nresults, int msgh)
?* 以保護模式調用具有"nargs"個參數(shù),"nresults"個返回值得函數(shù)。函數(shù)在第一個參數(shù)的前一個位置。
?* 保護模式指的是當調用出錯時不會報錯,而是返回一個錯誤碼同時將錯誤信息入棧。
?* 當調用成功時,函數(shù)返回0。將函數(shù)名以及參數(shù)出棧,之后將函數(shù)的返回值入棧。
?* 無論函數(shù)返回多少個返回值,Lua會調整為你需要的數(shù)量,忽略多余的或者將不夠的補為"nil"。
?* 當調用出錯時,函數(shù)返回非0值。將函數(shù)名以及參數(shù)出棧,
?* 以錯誤信息作為參數(shù),執(zhí)行虛擬棧中索引"msgh"處的出錯處理函數(shù),
?* 將出錯處理函數(shù)的返回值作為"lua_pcall"的返回值入棧。
?* "msgh"為0代表沒有錯誤處理函數(shù),錯誤處理函數(shù)必須要在被調用函數(shù)和其參數(shù)入棧之前入棧。
?* 典型的用法中,錯誤處理函數(shù)被用來給錯誤消息加上更多的調試信息,比如棧跟蹤信息。
?* 這些信息在"lua_pcall"返回后,由于棧已經(jīng)展開,所以收集不到了。
?* lua_pcall 函數(shù)會返回下列常數(shù)(定義在"lua.h"內)中的一個:
? ?LUA_OK (0): 成功。
? ?LUA_ERRRUN: 運行時錯誤(一般錯誤)。
? ?LUA_ERRMEM: 內存分配錯誤(此種情況,Lua不會調用錯誤處理函數(shù))。
? ?LUA_ERRERR: 在運行錯誤處理函數(shù)時發(fā)生的錯誤(此種情況,Lua不會再次調用錯誤處理函數(shù))。
? ?LUA_ERRGCMM: 在運行"__gc"元方法時發(fā)生的錯誤(這個錯誤和被調用的函數(shù)無關。)。
?
#include <iostream>
#include <lua.hpp>/* // lua.hpp 中的內容
// lua 是以ANSI C編寫的, 所以在C++中使用必須加上 extern "C" { } , 顯示的告訴編譯器以C的方式編譯代碼
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
*//** Lua中的字符串可以不以'\0'作為結束符。這樣,字符串中可以包含任意的二進制(甚至是'\0'),字符串的長度由明確的長度指定* 在lua_pushlstring()、lua_pushliteral()以及l(fā)ua_pushstring()中,Lua不保存字符串(變量)指針。因此當這些函數(shù)返回時,你就可以修改你的字符串了* 遍歷一個”table”時,不要將lua_tolstring()作用在”key”上,這樣會導致lua_next()無法正常運行** 對于入棧是否有棧空間的情況,你需要自己判斷,別忘了現(xiàn)在你是一個C程序員。當Lua啟動或者任何Lua調用C的時候,虛擬棧中至少有20個空間(在”lua.h”中LUA_MINSTACK定義),這對于一般情況下夠用了,所以一般不用考慮。但有時候確實需要更多的棧空間(比如調用一個不定參數(shù)的函數(shù)),此時你需要使用lua_checkstack檢查棧空間的情況** int lua_checkstack(lua_State *L, int sz)* 確保堆棧上至少有"n"個額外空位。如果不能把堆棧擴展到相應的尺寸,函數(shù)返回"false"。* 失敗的原因包括將把棧擴展到比固定最大尺寸還大(至少是幾千個元素)或分配內存失敗。* 這個函數(shù)永遠不會縮小堆棧,如果堆棧已經(jīng)比需要的大了,那么就保持原樣。** 在平常的編碼中,對于執(zhí)行失敗時會返回0的lua_to*()類別的函數(shù),我們最好先使用lua_is*()類別的函數(shù)判斷參數(shù)的類型,之后再使用lua_to*()類別的函數(shù)對參數(shù)進行轉換;而對于執(zhí)行失敗時會返回NULL的lua_to*()類別的函數(shù),我們可以直接使用lua_to*()類別的函數(shù)直接對參數(shù)進行轉換,判斷函數(shù)的返回值非NULL與否,就能判斷轉換是否成功** lua_pop()就是通過lua_settop()實現(xiàn)的(在”lua.h”中定義)* #define lua_pop(L,n) lua_settop(L, -(n)-1)** 以下操作對于虛擬棧沒有任何影響, 棧中元素個數(shù)還是一樣多* lua_settop(L, -1); // set top to its current value* lua_insert(L, -1); // move top element to the top* lua_replace(L, -1); // replace top element by the top element**/static void stackDump(lua_State * L)
{int i = 0;int top = lua_gettop(L); // 獲取棧中元素個數(shù)std::cout << "lua stack value count: " << top << std::endl;for (i = 1; i <= top; ++i) // 遍歷棧中每一個元素 // 棧底的序號為1, 依次遞增. 棧頂?shù)男蛱柺冀K為-1{int t = lua_type(L, i); // 獲取元素的類型switch (t){case LUA_TSTRING: // stringsstd::cout << lua_tostring(L, i);break;case LUA_TBOOLEAN: // boolstd::cout << (lua_toboolean(L, i) != 0 ? "true" : "false");break;case LUA_TNUMBER: // numberstd::cout << lua_tonumber(L, i);break;default: // other valuesstd::cout << lua_typename(L, t); // 將宏定義的類型碼轉換為類型名稱break;}std::cout << " ";}std::cout << std::endl;
}int main()
{lua_State * L = luaL_newstate(); // 創(chuàng)建Lua虛擬機luaL_openlibs(L); // 打開Lua狀態(tài)機"L"中的所有Lua標準庫// 向虛擬棧中壓入值lua_pushboolean(L, 1); // truelua_pushnumber(L, 10); // 10lua_pushnil(L); // nillua_pushstring(L, "hello"); // "hello"stackDump(L); // true 10 nil 'hello'lua_pushvalue(L, -4); // 將索引-4處的值的副本入棧stackDump(L); // true 10 nil 'hello' truelua_replace(L, 3); // 將棧頂元素移動到索引3處,并覆蓋原先的元素stackDump(L); // true 10 true 'hello'lua_settop(L, 6); // 將棧頂設置為索引6處,多出來的新元素被賦值為"nil"stackDump(L); // true 10 true 'hello' nil nillua_remove(L, -3); // 移除索引-3處的元素,其上所有元素下移stackDump(L); // true 10 true nil nillua_settop(L, -5); // 將棧頂設置為索引-5處stackDump(L); // truelua_close(L); // 關閉Lua狀態(tài)機std::cout << "..." << std::endl;system("pause");return 0;
}
?
總結
以上是生活随笔為你收集整理的Lua 和 C 交互中虚拟栈的操作和遍历的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。