Lua从入门到放弃--程序接口

时间:2022-06-01 19:27:59

今天上午烈日当头,各种美女白色短袖,到了下午两点左右,哈哈,这暴雨下的,淋的各种透明,红的,黑的,蓝的,你们懂得.....五一小长假,出去浪了一圈,我只想说高速真TMD堵....


这个部门描述了lua的C API,也就是宿主程序跟lua通讯用的一组C函数。所有的API函数按相关的类型以及常量都声明在头文件lua.h中。

虽然我们说的是“函数”,但一部分简单的 API 是以宏的形式提供的。 所有的这些宏都只使用它们的参数一次 (除了第一个参数,也就是 lua 状态机,之后写一个lua状态机的例子出来), 因此你不需担心这些宏的展开会引起一些副作用。

在所有的 C 库中,lua API 函数都不去检查参数的有效性和坚固性。 然而,你可以在编译 Lua 时加上打开一个宏开关来开启luaconf.h文件中的宏luai_apicheck以改变这个行为。


lua使用一个虚拟栈来和C传递值。栈上的每个元素都是一个lua值(nil,数字,字符串等等)

无论何时lua调用C,被调用的函数都得到一个新的栈,这个栈独立于C函数本身的栈,也独立于其他函数的栈。它里面包含了lua传递给C函数的所有参数,而C函数则把要返回的结果也放入堆栈以返回给调用者。

方便起见,所有针对栈的API查询操作都不严格遵循栈的操作规则。而是可以用一个索引来指向栈上的绝对位置;负的索引则从栈顶开始的偏移量。如果堆栈有n个元素,那么索引1表示第一个元素,也就是最先被压入堆栈的元素,而索引n则是最后一个元素;索引-1指最后一个元素,即栈顶的元素;索引-n则指的是第一个元素。如果索引在1到栈顶之间,我们就称之为有效索引。


当你使用lua API时,就有责任保证其坚固性。特别需要注意的是,你有责任控制不要堆栈溢出。你可以使用lua_checkstack这个函数来扩大可用堆栈的尺寸。

无论何时lua调用C, 它都只保证LUA_MINSTACK这么多的堆栈空间可以使用。LUA_MINSTACK一般被定义为20,因此,只要你不是不断的把数据压栈,通常你不需要关心堆栈的大小。

所有的查询函数都可以接收一个索引,只要这个索引是任何栈提供的空间中的值。栈能提供的最大空间是通过lua_checkstack来设置的。这些索引被称作可接受的索引,通常我们把它定义为:

(index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace)

注意,0永远都不是一个可接收的索引。


除了特别声明外,任何一个函数都可以接收另一个有效的索引,他们被称为伪索引。这个可以帮助C代码访问一些并不在栈上的lua值。伪索引被用来访问线程的环境,函数的环境,注册表,还有C函数的upvalue。

线程的环境通常在伪索引LUA_GLOBALSINDEX处。正在运行的C函数的环境则放在伪索引LUA_ENVIRONINDEX处。

你可以用常规的table操作来访问和改变全局变量的值,只需要指定环境表的位置。例如:

lua_getfield(L, LUA_GLOBALSINDEX, varname);


当C函数被创建出来, 我们有可能会把一些值关联在一起, 也就是创建一个C closure;这些被关联起来的值被叫做upvalue, 他们可以在函数被调用的时候访问到。

无论何时去调用C函数,函数的upvalue都被放在指定的伪索引处。我们可以用lua_upvalueindex这个宏来生成这些伪索引。第一个关联到函数的值放在lua_upvalueindex(1)位置处,以此类推。任何情况都可以使用lua_upvalueindex(n)产生一个upvalue的索引,即使n大于实际的upvalue数量也可以。它都可以产生一个可接受但不一定有效的索引。


lua还提供了一个注册表,这是一个预定义出来的表,可以用来保证任何C代码想保存的lua值。这个表可以用伪索引LUA_REGISTERINDEX来访问。任何C库都可以在这张表里保存数据,为了防止冲突,你需要特别小心的选择键名。一般的用法是,你可以用一个包含你的库名的字符串作为键名,或者可以取你自己C代码中的一个地址,以light userdata的形式做键。

注册表里的整数键被用于补充库中实现的索引系统的工作,一般说来不要他们用于别的用途。


本文参考lua手册  http://www.lua.org/manual/5.3/manual.html