C API
提供了下列用于通用栈操作的函数:
int lua_gettop (lua_State *L); void lua_settop (lua_State *L, int index); void lua_pushvalue (lua_State *L, int index); void lua_rotate (lua_State *L, int index, int n); void lua_remove (lua_State *L, int index); void lua_insert (lua_State *L, int index); void lua_replace (lua_State *L, int index); void lua_copy (lua_State *L, int fromidx, int toidx);点击复制复制失败已复制
函数 lua_gettop
返回栈中元素的个数,也即栈顶元素的索引。函数 lua_settop
将栈顶设置为一个指定的值,即修改栈中的元素数量。如果之前的栈顶比新设置的更高,那么高出来的这些元素就会被丢弃;反之,该函数会向栈中压入 nil
来补足大小。特别的,函数 lua_settop(L, 0)
用于清空栈。在调用函数 lua_settop
时也可以使用负数索引;基于这个功能, C API
提供了下面的宏,用于从栈中弹出 n
个元素:
#define lua_pop(L, n) lua_settop(L, -(n) -1)点击复制复制失败已复制
函数 lua_pushvalue
用于将指定索引上的元素的副本压入栈。
函数 lua_rotate
是 Lua5.3
中新引入的。顾名思义,该函数将指定索引的元素向栈顶转动n
个位置。若 n
为正数,表示将元素向栈顶方向移动,而 n
为负数则表示向相反的方向转动。这是一个非常有用的函数,另外两个 C API
操作实际上是基于使用该函数的宏定义的。其中一个是 lua_remove
,用于删除指定索引的元素,并将该位置之上的所有元素下移以填补空缺,其定义如下:
# define lua_remove(L, idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))点击复制复制失败已复制
也就是说,该函数会将栈转动一格,把想要的那个元素移动到栈顶,然后弹出该元素。
另一个宏是 lua_insert
,用于将栈顶元素移动到指定位置,并上移指定位置之上的所有元素以开辟出一个元素的空间:
# define lua_insert(L, idx) lua_rotate(L, (idx), 1)点击复制复制失败已复制
函数 lua_replace
弹出一个值,并将栈顶设置为自定索引上的值,而不移动任何元素。最后,函数 lua_copy
将一个索引上的值复制到另一个索引上,并且原值不受影响。
提示
函数 lua_copy
是在 Lua5.2
中引入的。
请注意:以下的操作不会对空栈产生影响:
lua_settop(L, -1); // 将栈顶设置为当前的值 lua_insert(L, -1); // 将栈顶的元素移动到栈顶 lua_copy(L, x, x); // 把一个元素复制到它当前的位置 lua_rotate(L, x, 0); // 旋转零个位置点击复制复制失败已复制
演示示例:
#include <stdio.h> #include "lauxlib.h" #include "lua.h" static void stackDump(lua_State *L) { int i; 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; } } printf(" "); // 输出分隔符 } printf("\n"); // 换行符 } int main(void) { lua_State *L = luaL_newstate(); lua_pushboolean(L, 1); lua_pushnumber(L, 10); lua_pushnil(L); lua_pushstring(L, "hello"); stackDump(L); // --> true 10 nil 'hello' lua_pushvalue(L, -4); stackDump(L); // --> true 10 nil 'hello' true lua_replace(L, 3); stackDump(L); // --> true 10 true 'hello' lua_settop(L, 6); stackDump(L); // --> true 10 true 'hello' nil nil lua_rotate(L, 3, 1); stackDump(L); // --> true 10 nil true 'hello' nil lua_remove(L, -3); stackDump(L); // --> true 10 nil 'hello' nil lua_settop(L, -5); stackDump(L); // --> true lua_close(L); return 0; }