迷惘的码农。
分类:
2008-08-15 11:15:15
本节描述用于Lua的C API,即可用于宿主程序和Lua通信的C函数集合。所有API函数和相关的类型和常量在头文件中声明。
即使当我们使用术语“函数”时,API中的任何设备可能改为宏提供。所有这些宏严格地只使用它们的每个参数一次(除了第一参数,它总是个Lua状态机),因此不要产生任何隐藏的副作用(side-effects)。
同多数C库一样,Lua API函数不会检查它们的参数的可用性和一致性。可是,你可通过为文件luaconf.h
中的宏使用适当的定义编译Lua来改变这种行为。
Lua用一个虚拟栈(virtual stack)向或从C传值。该栈中的每个元素表示一个Lua值(nil、数字、字符串,等等)。
无论何时Lua调用C,被调用函数得到一个新栈,它与以前的栈和一直活动的C函数的栈都无关。该栈最初包含传入C函数的任何参数,并且它也是C函数压入要被返回到调用者的结果的地方(见)。
为了方便的目的,API中的多数查询操作并不遵循严格的栈规范。而是通过使用index可引用栈中的任何元素:正数索引表示绝对的栈位置(从1开始);负数索引表示相对于栈顶的偏移。更明确地说,如果栈有n个元素,则索引1表示第一个元素(即第一个压入栈的元素),索引n表示最后的元素;索引-1也表示最后的元素(即栈顶的元素),索引-n表示第一个元素。如果索引处于1和栈顶之间(就是说如果1 ≤ abs(index) ≤ top
)我们说它是有效的。
当你同Lua API交互时,你有责任确保可靠性。特别地,你有责任控制栈溢出。你可用函数增长栈尺寸。
无论何时Lua调用C,它确保至少栈位置是可用的。LUA_MINSTACK
被定义为20,所以通常不需要担心栈空间,除非你的代码循环将元素压栈。
多数查询函数接受的索引为可用的栈空间内的任何值,即一直到你通过设置的最大栈尺寸。 这样的索引称为认可的索引。认可的索引更正式地定义如下:
(index < 0 && abs(index) <= top) ||
(index > 0 && index <= stackspace)
注意0决不是认可的索引。
除非另有说明,任何接受有效索引的函数也能用伪索引调用,它们表示C代码可访问但是并不在栈中的某些Lua值。伪索引用于访问线程环境、函数环境、注册表和C函数的upvalue(见)。
线程环境(其中存在全局变量)总是在伪索引处。正运行的C函数的环境总在伪索引处。
要访问和改变全局变量的值,你可在环境表上使用常规的表操作。例如,要访问一个全局变量的值,执行
lua_getfield(L, LUA_GLOBALSINDEX, varname);
当一个C函数被创建时,它可能关联了一些值,这样创建了一个C闭包;这些值称为upvalue,并且不论何时调用,它们对函数都是可访问的(见)。
只要一个C函数被调用,其upvalue就被定位在特定的伪索引处。这些伪索引由宏产生。关联到函数的第一个值在位置lua_upvalueindex(1)
处,依次类推。任何访问lua_upvalueindex(n)
,其中n大于当前函数的upvalue的数量,产生一个可接受(但无效)的索引。
Lua提供一个registry,它是个预定义表,可被任何C代码用来存储它需要存储的任何Lua值。该表总是定位于伪索引处。任何C库都能存储数据到该表中,但是它应该小心地选择不同于其他库用到的键,以避免冲突。典型地,你应该在你的代码中使用含有你的库名的字符串或带有C对象地址的轻量级用户数据作为键。
注册表中的整数键被辅助库实现的引用机制使用,因此不应该用作其他目的。
Lua在内部使用C的longjmp
设备处理错误。(如果你用C++也可选择使用一场;见文件luaconf.h
。)当Lua面临任何错误时(例如内存分配错误、类型错误、语法错误和运行时错误这样的),它抛出(raise)一个错误;即执行一个长跳转。受保护的环境使用setjmp
设置一个还原点;发生任何错误会跳到最近(时间上)活动的还原点。
Lua中的多数函数可能抛出错误,例如内存分配错误。每个函数的文档指出它能否抛出错误。
在C函数内可通过调用抛出错误。