值得一提是lua_tolstring函数,它的函数原型是const char *lua_tolstring (lua_State *L, int index, size_t *len)。它会把栈中索引为index的Lua值装换为一个C字符串。若参数Len不为NULL,则*Len会保存字符串的长度。栈中的Lua值必须为string或number类型,否则函数返回NULL。若栈中Lua值为number类型,则该函数实质会改变栈中的值为string类型,由于这个原因,在利用lua_next遍历栈中的table时,对key使用lua_tolstring尤其需要注意,除非知道key都是string类型。lua_tolstring函数返回的指针,指向的是Lua虚拟机内部的字符串,这个字符串是以'\0'结尾的,但字符串中间也可能包含值为0的字符。由于Lua自身的垃圾回收,因此当栈中的字符串被弹出后,函数返回的指针所有指向的字符串可能就不能再有效了。也说明了,当一个C函数从Lua收到一个字符串参数时,在C函数中,即不能在访问字符串时从栈中弹出它,也不能修改字符串。
3、其他操作栈的函数
int lua_call (lua_State *L, int nargs, int nresults);
调用栈中的函数,在调用lua_call之前,程序必须首先要保证被调用函数已压入栈,其次要被调用函数需要的参数也已经按顺序压入栈,也就是说,第一个参数最先被压入栈,依次类推。nargs是指需要压入栈中参数的个数,当函数被调用后,之前压入的函数和参数都会从栈中弹出,并将函数执行的结果按顺序压入栈中,因此最后一个结果压入栈顶,同时,压入栈的个数会根据nresults的值做调整。与lua_call相对应的是lua_pcall函数,lua_pcall会以保护模式调用栈中的函数。以保护模式调用意思是,当被调用的函数发生任何错误时,该错误不会传播,不像lua_call会把错误传递到上一层,lua_pcall所调用的栈中函数发送错误时,lua_pcall会捕捉这个错误,并向栈中压入一个错误信息,并返回一个错误码。在应用程序中编写主函数时,应该使用lua_pcall来调用栈中的函数,捕获所有错误。而在为Lua编写扩展的C函数时,应该调用lua_call,把错误返回到脚本层。
void lua_createtable (lua_State *L, int narr, int nrec);
创建一个新的table,并把它压入栈顶,参数narr和nrec分别指新的table将会有多少个数组元素和多少需要hash的元素,Lua会根据这个两个值为新的table预分配内存。对于事先知道table结构,利用这两个参数能提高创建新table的性能。对于事先不知道table结构,则可以使用void lua_newtable (lua_State *L),它等价于lua_createtable(L, 0, 0)。
除了上面提到的C API,还有许多其他有用的C API,比如操作table的接口有:lua_getfield、lua_setfield、lua_gettable、lua_settable等接口,在具体使用时,可以参照Lua手册。