标签:
首先我们来讲一下栈:
lua与c语言通讯的主要方法是通过一个无所不在的虚拟栈。几乎所有的api调用都会操作这个栈上的值:所有的数据交换,无论是lua到c语言或c语言到lua都是通过这个栈来完成。栈可以解决lua与c语言之间存在的两大差异,第一个差异时lua使用垃圾回收收集,而c语言要求显示地释放内存;第二种是lua使用动态类型,而c语言使用静态类型。
我们来看一下c与lua之间是怎么通讯的:(假如c语言想知道lua中的money字符串的值)
1.c想获取lua中的money字符串的值,需要c把money房放到栈顶,以便lua能看到。
2.lua从栈顶中获取money,此时栈顶再次变为空
3.lua通过money这个字段在其全局表中进行查找
4.全局表返回money对应的值,假设为10000
5.lua把取得的10000放到栈顶
6.c可以从栈顶取得10000
我们来看一下栈的操作:
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);
标签:
原文地址:http://my.oschina.net/u/815187/blog/486660