24.2.3 其他堆栈操作

除开上面所提及的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_remove (lua_State *L, int index);

void lua_insert (lua_State *L, int index);

void lua_replace (lua_State *L, int index);

函数lua_gettop返回堆栈中的元素个数,它也是栈顶元素的索引。注意一个负数索引-x对应于正数索引gettop-x+1lua_settop设置栈顶(也就是堆栈中的元素个数)为一个指定的值。如果开始的栈顶高于新的栈顶,顶部的值被丢弃。否则,为了得到指定的大小这个函数压入相应个数的空值(nil)到栈上。特别的,lua_settop(L,0)清空堆栈。你也可以用负数索引作为调用lua_settop的参数;那将会设置栈顶到指定的索引。利用这种技巧,API提供了下面这个宏,它从堆栈中弹出n个元素:

#define lua_pop(L,n)  lua_settop(L, -(n)-1)

函数lua_pushvalue压入堆栈上指定索引的一个抟贝到栈顶;lua_remove移除指定索引位置的元素,并将其上面所有的元素下移来填补这个位置的空白;lua_insert移动栈顶元素到指定索引的位置,并将这个索引位置上面的元素全部上移至栈顶被移动留下的空隔;最后,lua_replace从栈顶弹出元素值并将其设置到指定索引位置,没有任何移动操作。注意到下面的操作对堆栈没有任何影响:

lua_settop(L, -1);   /* set top to its current value */

lua_insert(L, -1);   /* move top element to the top */

为了说明这些函数的用法,这里有一个有用的帮助函数,它dump整个堆栈的内容:

static void stackDump (lua_State *L) {

    int i;

    int top = lua_gettop(L);

    for (i = 1; i <= top; i++) {  /* repeat for each level */

       int t = lua_type(L, i);

       switch (t) {

 

       case LUA_TSTRING:  /* strings */

           printf("`%s'", lua_tostring(L, i));

           break;

 

       case LUA_TBOOLEAN:  /* booleans */

           printf(lua_toboolean(L, i) ? "true" : "false");

           break;

 

       case LUA_TNUMBER:  /* numbers */

           printf("%g", lua_tonumber(L, i));

           break;

   

       default/* other values */

           printf("%s", lua_typename(L, t));

           break;

 

       }

       printf("  ");  /* put a separator */

    }

    printf("\n");     /* end the listing */

}

这个函数从栈底到栈顶遍历了整个堆栈,依照每个元素自己的类型打印出其值。它用引号输出字符串;以%g的格式输出数字;对于其它值(table,函数,等等)它仅仅输出它们的类型(lua_typename转换一个类型码到类型名)。

下面的函数利用stackDump更进一步的说明了API堆栈的操作。

#include <stdio.h>

#include <lua.h>

 

static void stackDump (lua_State *L) {

    ...

}

 

int main (void) {

    lua_State *L = lua_open();

    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_remove(L, -3); stackDump(L);

           /* true  10  true  nil  nil  */

 

    lua_settop(L, -5); stackDump(L);

           /* true  */

 

    lua_close(L);

    return 0;

}


相关链接:
lua程序设计目录 - 中国lua开发者 - lua论坛