Lua manual翻译——第三章第一、二节
因为受到经济危机的影响,我在 bokee.com 的博客可能随时出现无法访问的情况;因此将2005年到2006年间在 bokee.com 撰写的博客文章全部迁移到 csdn 博客中来,本文正是其中一篇迁移的文章。
3 - 应用编程接口(API)
这一节讲述Lua的C API, 宿主程序能够通过这一系列的C函数和Lua程序交互.所有的API函数及相关的类型定义和静态变量等都在名为lua.h的头文件中声明.
尽量我们使用“函数”这一术语,事实上为了方便,API都用宏的方式提供,所有的这些宏准确地使用它的每一个参数一次(除了第一个参数,它总是一个Lua state),因而不会产生隐藏的副作用。
3.1 - States
Lua连接库是完全可重入的,因为它没有全局变量。Lua解释器的整个state(如全局变量、堆栈等)都存储在一个结构类型为Lua_State动态分配的对象里。指向这一对象的指针必须作为第一个参数传递给所有连接库的API,除了用来生成一个Lua state的函数——lua_open。在调用所有的API函数之前,你必须先用lua_open以生成一个state:
lua_State* lua_open(void);
可以通过调用lua_close来释放一个通过lua_open生成的state:
void lua_close (lua_State *L);
这一函数销毁给定的Lua_State中的所有对象并释放state所占用的动态内存(如果有必要的话将通过调用对应的垃圾收集元方法来完成),在某些平台上,你不必调用这个函数,因为当宿主程序退出时会释放所有的资源,换句话说,长期运行的程序,如守护进程或web服务器,应尽快释放state所占的资源,以避免其过于庞大。
3.2 - 堆栈与索引
Lua使用虚拟堆栈机制和C程序互相传值,所有的堆栈中的元素都可以看作一个Lua值(如nil,number,string等)。
当Lua调用C函数时,被调用的C函数将得到一个新的堆栈。这一堆栈与之前调用此函数的堆栈无关,也有其它C函数的堆栈无关。这一新的堆栈用调用C函数要用到的参数初始化,同时,这一堆栈也被用以返回函数调用结果。
为了便于操作,在API的中大量操作都并不依从堆栈只能操作栈顶元素的严格规则。而通过索引引用堆栈的任一元素。一个正整数索引可以看作某一元素在堆栈中的绝对位置(从1开始计数),一个负整数索引可以看作某一元素相对于栈顶的偏移量。特别地,如果堆栈中有n个元素,那么索引1指向第一个元素(即第一个压入栈的元素)索引n指向最后一个元素;反过来,索引-1指向最后一个元素(即栈顶元素)索引-n指向第一个元素。当一个索引大于1并小于n时我们称其为一个有效索引(即1 <= abs(index) <= top)。
在任何时候,你都可以通过调用lua_gettop函数取得栈顶元素的索引:
int lua_gettop (lua_State *L);
因为索引从1开始计数,lua_gettop的返回值等于这个堆栈的元素个数(当堆栈为空时返回值为0)。
当你使用Lua API的时候,你有责任控制堆栈溢出。函数
int lua_checkstack (lua_State *L, ine extra);
将把堆栈的尺寸扩大到可以容纳top+extra个元素;当不能扩大堆栈尺寸到这一尺寸时返回假。这一函数从不减小堆栈的尺寸;当前堆栈的尺寸大于新的尺寸时,它将保留原来的尺寸,并不变化。
任何时候Lua调用C,都可以保证最少有LUA_MINSTACK个堆栈位置是可用的。LUAMINSTACK在lua.h文件的第20行定义,因此通常情况下不用担心堆栈空间不足,除非你的函数中循环向堆栈中压入元素。
大部分查询函数接受小于你通过lua_checkstack设置的堆栈尺寸的最大值的索引。这样的索引叫做可接受索引,更正式地说,我们可以用下面的语句定义一个可接受索引:
(index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace)
记得0永远不是一个可接受索引。
如非特别指出,任何函数接受的有效索引同样可称作假索引,即为一些可以使用C代码存取但并不存在于堆栈的Lua值。假索引被用以存取全局环境,注册表,和相对于C函数可见的Lua程序局部变量。