從寫上一篇Lua的文章到現(xiàn)在,已經(jīng)過去半月有余了,是時候讓自己的Lua狀態(tài)refresh一下了。本教程將介紹Lua的棧及基本棧操作,同時還有如何在C/C++代碼里面讀取Lua的Table。
理解Lua棧
Lua通過一個“虛擬?!迸cC/C++程序進行數(shù)據(jù)交互,所有的Lua C API都是通過操作這個棧來完成相應(yīng)的數(shù)據(jù)通信。 Lua的這個“虛擬棧”解決了C/C++程序與Lua程序通信的兩大問題:
1.Lua使用垃圾回收,而C/C++需要手動管理內(nèi)存。
2.Lua使用動態(tài)類型,而C/C++使用的是靜態(tài)類型。
因為這個棧在Lua虛擬機內(nèi)部,當一個Lua的變量放在棧里面的時候,虛擬機可以知道它有沒有被宿主程序所使用,從而決定是否采用GC。另外Lua采用結(jié)構(gòu)體封裝了類似“Lua_Value”的類型,讓它可以存儲任何C的類型。從而在數(shù)據(jù)交換的時候,任何類型都可以被放入棧的一個slot中。
由于棧是FILO的,所以,當我們在Lua里面操作這個棧的時候,每次操作的都是棧的頂部。而Lua的C API則有更多的控制權(quán),它可以非常靈活地操縱這個棧的任意位置的元素。
基本Lua棧操作
1.往棧里面壓入一個值
復(fù)制代碼 代碼如下:
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_pushunsigned (lua_State *L, lua_Unsigned n);
void lua_pushlstring (lua_State *L, const char *s, size_t len);
void lua_pushstring (lua_State *L, const char *s);
2.查詢棧里面的元素
復(fù)制代碼 代碼如下:
int lua_is* (lua_State * L, int index);
這里面的*可以是boolean,nil,string,function等等
3.獲取棧內(nèi)給定位置的元素值
復(fù)制代碼 代碼如下:
xxx lua_toXXX(lua_State * L, int index);
這里面的xxx可以是nil, boolean, string,integer等等。
4.其它棧操作
復(fù)制代碼 代碼如下:
//取得棧中元素個數(shù)
int lua_gettop (lua_State *L);
//設(shè)置棧的大小為一個指定的值,而lua_settop(L,0)會把當前棧清空
//如果指定的index大于之前棧的大小,那么空余的空間會被nil填充
//如果index小于之前的棧中元素個數(shù),則多余的元素會被丟棄
void lua_settop (lua_State *L, int index);
//把棧中index所在位置的元素壓入棧
void lua_pushvalue (lua_State *L, int index);
//移除棧中index所在位置的元素
void lua_remove(lua_State *L, int index);
//在棧的頂部的元素移動至index處
void lua_insert(lua_State *L, int index);
//從棧頂彈出一個值,并把它設(shè)置到給定的index處
void lua_replace(lua_State *L, int index);
//把fromidx處的元素copy一份插入到toidx,這操作不會修改fromidx處的元素
void lua_copy(lua_State *L, int fromidx, int toidx);
另外,根據(jù)《Programming In Lua》一書中的所講,我們可以定義一個函數(shù)stackDump來打印當前棧的情況:
復(fù)制代碼 代碼如下:
static void stackDump(lua_State* L){
cout"\nbegin dump lua stack"endl;
int i = 0;
int top = lua_gettop(L);
for (i = 1; i = top; ++i) {
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING:
{
printf("'%s' ", lua_tostring(L, i));
}
break;
case LUA_TBOOLEAN:
{
printf(lua_toboolean(L, i) ? "true " : "false ");
}break;
case LUA_TNUMBER:
{
printf("%g ", lua_tonumber(L, i));
}
break;
default:
{
printf("%s ", lua_typename(L, t));
}
break;
}
}
cout"\nend dump lua stack"endl;
}
C/C++訪問Lua的Table
假設(shè)我們的Lua文件中有一個Table為:
復(fù)制代碼 代碼如下:
me = { name = "zilongshanren", age = 27}
我們可以通過以下C代碼來訪問它的元素:
復(fù)制代碼 代碼如下:
//從Lua里面取得me這個table,并壓入棧
lua_getglobal(L, "me");
if (!lua_istable(L, -1)) {
CCLOG("error! me is not a table");
}
//往棧里面壓入一個key:name
lua_pushstring(L, "name");
//取得-2位置的table,然后把棧頂元素彈出,取出table[name]的值并壓入棧
lua_gettable(L, -2);
//輸出棧頂?shù)膎ame
CCLOG("name = %s", lua_tostring(L, -1));
stackDump(L);
//把棧頂元素彈出去
lua_pop(L, 1);
//壓入另一個key:age
lua_pushstring(L, "age");
//取出-2位置的table,把table[age]的值壓入棧
lua_gettable(L, -2);
stackDump(L);
CCLOG("age = %td", lua_tointeger(L, -1));
Lua5.1還引入了一個新方法:
復(fù)制代碼 代碼如下:
lua_getfield(L, -1, "age");
它可以取代
復(fù)制代碼 代碼如下:
//壓入另一個key:age
lua_pushstring(L, "age");
//取出-2位置的table,把table[age]的值壓入棧
lua_gettable(L, -2);
下篇文章,我們將介紹Lua如何調(diào)用C/C++里面的函數(shù)。
您可能感興趣的文章:- c++中explicit與mutable關(guān)鍵字的深入探究
- C++中const、volatile、mutable使用方法小結(jié)
- C++中mutable與volatile的深入理解
- 淺談C++中的mutable和volatile關(guān)鍵字
- C++中MFC Tab Control控件的使用詳解
- C++遍歷Lua table的方法實例
- c++遍歷lua table示例
- 深入解析C++中的mutable關(guān)鍵字
- c++關(guān)鍵字mutable深入解析
- C++解析特殊符號tab和換行符號詳情