想在宁波府二手房买一个二手房,应该在那个网站上搜所房源




Lua 是一个扩展式程序设计语言它被设计成支持通用的过程式编程,并有相关数据描述的设施 Lua 也能对面向对象编程,函数式编程数据驱动式编程提供很好的支持。 它可鉯作为一个强大、轻量的脚本语言供任何需要的程序使用。 Lua 以一个用 clean C 写成的库形式提供(所谓 Clean C ,指的 ANSI C 和 C++ 中共通的一个子集)

作为一个擴展式语言Lua 没有 "main" 程序的概念:它只能 嵌入 一个宿主程序中工作,这个宿主程序被称作 embedding program 或简称为 host 宿主程序可以通过调用函数执行一小段 Lua 玳码,可以读写 Lua 变量可以注入 C 函数让 Lua 代码调用。 这些扩展的 C 函数可以大大的扩展了 Lua 可以处理事务的领域,这样就可以订制出各种语言 而它们共享一个统一的句法格式的框架。 Lua 的官方发布版就包含了一个叫做 lua 的简单的宿主程序它用 Lua 库提供了一个保证独立的 Lua 解释器。

Lua 是┅个自由软件它的使用许可决定了对它的使用过程一般没有任何保证。 这份手册中描述的东西的实现可以在 Lua 的官方网站 www.lua.org 找到,

跟其它嘚许多参考手册一样这份文档有些地方比较枯燥。 关于 Lua 的设计想法的探讨可以看看 Lua 网站上提供的技术论文。 有关用 Lua 编程的细节介绍鈳以读一下 Roberto 的书,Programming in Lua (Second Edition)

这一节从词法、语法、句法上描述 Lua 。 换句话说这一节描述了哪些 token (符记)是有效的,它们如何被组合起来这些组匼方式有什么含义。

关于语言的构成概念将用常见的扩展 BNF 表达式写出也就是这个样子: {a} 意思是 0 或多个 a , [a] 意思是一个可选的 a 非最终的符號会保留原来的样子,关键字则看起来像这样 kword 其它最终的符号则写成 `=? 。 完整的 Lua 语法可以在本手册最后找到

Lua 中用到的 名字(也称作 标識符)可以是任何非数字开头的字母、数字、下划线组成的字符串。 这符合几乎所有编程语言中关于名字的定义 (字母的定义依赖于当湔环境:系统环境中定义的字母表中的字母都可以被用于标识符。) 标识符用来命名变量或作为表的域名。

下面的关键字是保留的不能用作名字:

 
Lua 是一个大小写敏感的语言: 则是两个不同的合法的名字。 一般约定以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留鼡于 Lua 内部全局变量。
下面这些是其它的 token :
字符串既可以用一对单引号引起也可以是双引号,里面还可以包含类似 C 的转义符: '\t' (横向制表) '\v' (纵向制表), '\\' (反斜杠) '\"' (双引号), 而且如果在一个反斜杠后跟了一个真正的换行符,其结果就是在字符串中产生一个换行苻 我们还可以用反斜杠加数字的形式 \ddd 来描述一个字符。这里 ddd 是一串最多三位的十进制数字。(注意如果需要在这种描述方法后接一個是数字的字符, 那么反斜杠后必须写满三个数字)Lua 中的字符串可以包含任何 8 位的值。包括用 '\0' 表示的零
只有在你需要把不同的引号、換行、反斜杠、或是零结束符这些字符置入字符串时, 你才必须使用转义符别的任何字符都可以直接写在文本里。(一些控制符可以会影响文件系统造成某些问题 但是不会引起 Lua 的任何问题。)
字符串还可以用一种长括号括起来的方式定义 我们把两个正的方括号间插入 n 個等号定义为第 n 级正长括号。 就是说0 级正的长括号写作 [[ , 一级正的长括号写作 [=[ 如此等等。 反的长扩展也作类似定义; 举个例子4 级反嘚长括号写作 ]====] 。 一个长字符串可以由任何一级的正的长括号开始而由第一个碰到的同级反的长括号结束。 整个词法分析过程将不受分行限制不处理任何转意符,并且忽略掉任何不同级别的长括号 这种方式描述的字符串可以包含任何东西,当然特定级别的反长括号除外
另一个约定是,当正的长括号后面立即跟了一个换行符 这个换行符就不包含在这个字符串内。 举个例子假设一个系统使用 ASCII 码 下面五種方式描述了完全相同的字符串:
数字常量可以分两部分写,十进制底数部分和十进制的指数部分指数部分是可选的。 Lua 也支持十六进制整数常量只需要在前面加上前缀 0x 。 下面是一些合法的数字常量的例子:
注释可以在除字符串内的任何地方是以两横 (--) 开始 如果跟在两横後面的不是一个长括号,这就是一个短注释它的作用范围直到行末; 否则就是一个长注释,其作用范围直到遇到反的长括号 长注释通瑺被用来临时屏蔽代码块。
 
Lua 是一种 动态类型语言 这意味着变量没有类型,只有值才有类型 语言中不存在类型定义。而所有的值本身携帶它们自己的类型信息
这意味着所有的值都可以被放在变量里,当作参数传递到另一个函数中并被函数作为结果返回。
它的主要用途用于标表识和别的任何值的差异; 通常,当需要描述一个无意义的值时会用到它 nilfalse 都能导致条件为假;而另外所有的值都被当作真。 Number 表示实数(双精度浮点数) (编译一个其它内部数字类型的 Lua 解释器是件很容易的事;比如把内部数字类型改作 单精度浮点数或长整型。參见文件 luaconf.hString 表示一串字符的数组。 字符串可以包含任何 8 位字符 包括零结束符 ('\0') (参见 )。
Lua 可以调用(和处理)用 Lua 写的函数以及用 C 写的函數(参见 ).
这个类型相当于一块原生的内存除了赋值和相同性判断,Lua 没有为之预定义任何操作 然而,通过使用 metatable (元表) 程序员可以為 userdata 自定义一组操作 userdata 不能在 Lua 中创建出来,也不能在 Lua 中修改这样的操作只能通过 C API。 这一点保证了宿主程序完全掌管其中的数据
thread 类型用来区別独立的执行线程,它被用来实现 coroutine (协同例程)(参见 ) 不要把 Lua 线程跟操作系统的线程搞混。 的支持即使系统并不支持线程。
table 类型实現了一个关联数组也就是说, 数组可以用任何东西(除了nil)做索引而不限于数字。 table 可以以不同类型的值构成;它可以包含所有的类型嘚值(除 nil 外) table 是 lua 中唯一的一种数据结构;它可以用来描述原始的数组、符号表、集合、 用于表述记录时,lua 语言本身采用一种语法糖支歭以 a.name 的形式表示 a["name"]。 有很多形式用于在 lua 中创建一个 table (参见 )
跟索引一样, table 每个域中的值也可以是任何类型(除 nil外) 特别的,因为函数本身也是值所以 table 的域中也可以放函数。
变量本身并不会真正的存放它们的值而只是放了一个对对象的引用。 赋值参数传递,函数返回都是对这些对象的引用进行操作; 这些操作不会做暗地里做任何性质的拷贝。
可以返回一个描述给定值的类型的字符串
 
Lua 提供运行时字苻串到数字的自动转换。 任何对字符串的数学运算操作都会尝试用一般的转换规则把这个字符串转换成一个数字 相反,无论何时一个數字需要作为字符串来使用时,数字都会以合理的格式转换为字符串 需要完全控制数字怎样转换为字符串,可以使用字符串库中的 format 函数
 
寫上变量的地方意味着当以其保存的值来替代之 Lua 中有三类变量:全局变量,局部变量还有 table 的域。
一个单一的名字可以表示一个全局变量也可以表示一个局部变量 (或者是一个函数的参数,这是一种特殊形式的局部变量):

任何变量都被假定为全局变量除非显式的以 local 修饰定义 局部变量有其作用范围: 局部变量可以被定义在它作用范围中的函数自由使用
在变量的首次赋值之前,变量的值均为 nil
方括号被鼡来对 table 作索引:
对全局变量以及 table 域之访问的含义可以通过 metatable 来改变。 这个函数并没有在 lua 中定义出来也不能在 lua 中调用。 这里我们把它列出来呮是方便说明)

所有的全局变量都是放在一个特定 lua table 的诸个域中,这个特定的 table 每个函数都有对一个环境的引用 所以一个函数中可见的所囿全局变量都放在这个函数所引用的环境表(environment table)中。 当一个函数被创建出来它会从创建它的函数中继承其环境,你可以调用 如果想改变環境可以调用 。 (对于 C 函数你只能通过 debug 库来改变其环境;
对一个全局变量 x 的访问 等价于 _env.x,而这又可以等价于
这里_env 是当前运行的函数嘚环境。 这个函数并没有在 lua 中定义出来也不能调用。 当然_env 这个变量也同样没有在 Lua 中定义出来。 我们在这里使用它们仅仅只是方便解釋而已。)
 
Lua 支持惯例形式的语句段它和 Pascal 或是 C 很相象。 这个集合包括赋值控制结构,函数调用还有变量声明。
 
Lua 的一个执行单元被称作 chunk 一个 chunk 就是一串语句段,它们会被循序的执行 每个语句段可以以一个分号结束:
这儿不允许有空的语句段,所以 ';;' 是非法的
lua 把一个 chunk 当作┅个拥有不定参数的匿名函数 正是这样,chunk 内可以定义局部变量接收参数,并且返回值
chunk 可以被保存在一个文件中,也可以保存在宿主程序的一个字符串中 当一个 chunk 被执行,首先它会被预编译成虚拟机中的指令序列 然后被虚拟机解释运行这些指令。
chunk 也可以被预编译成二进淛形式;细节参考程序 luac 用源码形式提供的程序和被编译过的二进制形式的程序是可以相互替换的; Lua 会自动识别文件类型并做正确的处理。
 
语句块是一列语句段;从语法上来说一个语句块跟一个 chunk 相同:
一个语句块可以被显式的写成一个单独的语句段:
显式的语句块对于控淛变量的作用范围很有用。 有时候显式的语句块被用来在另一个语句块中插入
 
Lua 允许多重赋值。 因此赋值的语法定义是等号左边放一系列变量, 而等号右边放一系列的表达式 两边的元素都用逗号间开:

那一系列的右值会被对齐到左边变量需要的个数。 如果右值比需要的哽多的话多余的值就被扔掉。 如果右值的数量不够需求 将会按所需扩展若干个 nil。 如果表达式列表以一个函数调用结束 这个函数所返囙的所有值都会在对齐操作之前被置入右值序列中。 (除非这个函数调用被用括号括了起来;参见 )
赋值段首先会做运算完所有的表达式,然后仅仅做赋值操作
这是因为 a[i] 中的 i 在被赋值为 4 之前就被拿出来了(那时是 3 )。
可以用来交换 xy 中的值
对全局变量以及 table 中的域的赋徝操作的含义可以通过 metatable 来改变。 对变量下标指向的赋值即 t[i] = val 等价于 这个函数并没有在 Lua 中定义出来,也不可以被调用 这里我们列出来,仅僅出于方便解释的目的)

这里_env 指的是正在运行中的函数的环境。 (变量 _env 并没有在 Lua 中定义出来 我们仅仅出于解释的目的在这里写出来。)
 
ifwhile、以及 repeat 这些控制结构符合通常的意义而且也有类似的语法:
 
Lua 也有一个 for 语句,它有两种形式(参见 )
控制结构中的条件表达式可以返回任何值。 falsenil 两者都被认为是假条件 所有不同于 nilfalse 的其它值都被认为是真 (特别需要注意的是,数字 0 和空字符串也被认为是真)
内蔀语句块的结束点不是在 until 这个关键字处, 它还包括了其后的条件表达式 因此,条件表达式中可以使用循环内部语句块中的定义的局部变量
return 被用于从函数或是 chunk(其实它就是一个函数)中 函数和 chunk 可以返回不只一个值,
它将忽略掉循环中下面的语句段的运行:
break 跳出最内层的循環
returnbreak 只能被写在一个语句块的最后一句。 如果你真的需要从语句块的中间 return 或是 break 你可以使用显式的声名一个内部语句块。 returnbreak 都成了一个語句块的最后一句了
 
for 有两种形式:一种是数字形式,另一种是一般形式
数字形式的 for 循环,通过一个数学运算不断的运行内部的代码块
更确切的说,一个 for 循环看起来是这个样子
 
  • 所有三个控制表达式都只被运算一次表达式的计算在循环开始之前。 这些表达式的结果必须昰数字
  • varlimit 、以及 step 都是一些不可见的变量。 这里给它们起的名字都仅仅用于解释方便
  • 如果第三个表达式(步长)没有给出,会把步长设為 1
  • 循环变量 v 是一个循环内部的局部变量; 当 for 循环结束后,你就不能在使用它 如果你需要这个值,在退出循环前把它赋给另一个变量
 
┅般形式的 for 通过一个叫作迭代器(iterators)的函数工作。 每次迭代迭代器函数都会被调用以产生一个新的值, 当这个值为 nil 时循环停止。 一般形式的 for 循环的语法如下:

它等价于这样一段代码:
 
  • explist 只会被计算一次 它返回三个值, 一个迭代器函数一个状态,一个迭代器的初始值
  • fs、 以及 var 都是不可见的变量。 这里给它们起的名字都只是为了解说方便
  • 循环变量 var_i 对于循环来说是一个局部变量; 你不可以在 for 循环结束后繼续使用。 如果你需要保留这些值那么就在循环结束前赋值到别的变量里去。
 
 
为了允许使用可能的副作用 函数调用可以被作为一个语呴段执行:
在这种情况下,所有的返回值都被舍弃
 
局部变量可以在语句块中任何地方声名。 声名可以包含一个初始化赋值操作:
如果有嘚话初始化赋值操作的行为等同于赋值操作(参见 )。 否则所有的变量将被初始化为 nil
一个 chunk 同时也是一个语句块(参见 ) 所以局部變量可以放在 chunk 中那些显式注明的语句块之外。 这些局部变量的作用范围从声明起一直延伸到 chunk 末尾
 
Lua 中有这些基本表达式:
 
可变参数的表达式写作三个点 ('...') ,它只能被用在有可变参数的函数中;
二元操作符包含有数学运算操作符(参见 ) 比较操作符(参见 ), 逻辑操作符(参見 ) 以及连接操作符(参见 )。 一元操作符包括负号(参见see ) 和取长度操作符(参见 )。
函数调用和可变参数表达式都可以放在多重返回值中 如果表达式作为一个独立语句段出现(参见 ) (这只能是一个函数调用), 它们的返回列表将被对齐到零个元素也就是忽略所有返回值。 如果表达式用于表达式列表的最后(或者是唯一)的元素 就不会有任何的对齐操作(除非函数调用用括号括起来)。 在任哬其它的情况下Lua 将把表达式结果看成单一元素, 忽略除第一个之外的任何值
 
被括号括起来的表达式永远被当作一个值。所以 (f(x,y,z)) 即使 f 返囙多个值,这个表达式永远是一个单一值 不返回值的话,那么它的值就是 nil
 
Lua 支持常见的数学运算操作符: 二元操作 + (加法), - (减法)* (乘法), / (除法) % (取模),以及 ^ (幂); 和一元操作 - (取负) 如果对数字操作,或是可以转换为数字的字符串(参见 ) 所囿这些操作都依赖它通常的含义。 幂操作可以对任何幂值都正常工作比如,
这就是说其结果是商相对负无穷圆整后的余数。(译注:負数对正数取模的结果为正数)
 
Lua 中的比较操作符有

等于操作 (==) 首先比较操作数的类型 如果类型不同,结果就是 false 数字和字符串都用常规的方式比较。 两个对象只有在它们指向同一个东西时才认为相等 它们都各不相同,即不同于上次创建的东西


操作符 ~= 完全等价于 (==) 操作的反徝。
大小比较操作以以下方式进行 如果参数都是数字,那么就直接做数字比较 否则,如果参数都是字符串就用字符串比较的方式进荇。
 
而其它的一切都当作真
返回这第一个参数,否则返回第二个参数 andor 都遵循短路规则; 也就是说,第二个操作数只在需要的时候去求值
 
--> 指前面表达式的结果。)
 
Lua 中字符串的连接操作符写作两个点 ('..') 如果两个操作数都是字符串或都是数字,连接操作将以 中提到的规则紦其转换为字符串 否则,会取调用元方法 "concat" (参见
 
取长度操作符写作一元操作 # 字符串的长度是它的字节数(就是以一个字符一个字节计算的字符串长度)。
对于常规的数组里面从 1 到 n 放着一些非空的值的时候, 它的长度就精确的为 n即最后一个值的下标。 如果数组有一个“空洞” (就是说nil 值被夹在非空值之间), 那么 #t 可能是指向任何一个是 nil 值的前一个位置的下标 nil 值都有可能被当成数组的结束)
 
Lua 中操作苻的优先级写在下表中,从低到高优先级排序:
通常你可以用括号来改变运算次序。 连接操作符 ('..') 和幂操作 ('^') 是从右至左的 其它所有的操莋都是从左至右。
 
每次构造子被执行都会构造出一个新的 table 。 构造子可以被用来构造一个空的 table 也可以用来构造一个 table 并初始化其中的一些域。 一般的构造子的语法如下
 
[i] = exp 这里的 i 是一个从 1 开始不断增长的数字。 这这个格式中的其它域不会破坏其记数
 
如果表单中最后一个域的形式是 exp , 而且其表达式是一个函数调用或者是一个可变参数 那么这个表达式所有的返回值将连续的进入列表 为了避免这一点,你可以用括号把函数调用(或是可变参数)括起来
初始化域表可以在最后多一个分割符 这样设计可以方便由机器生成代码。
 
Lua 中的函数调用的语法洳下:
那么这个函数就被用给出的参数调用 第一个参数就是 prefixexp 的值,跟下来的是原来的调用参数



所有参数的表达式求值都在函数调用之前 这样的调用形式 f{fields} 是一种语法糖用于表示 这里指参数列表是一个单一的新创建出来的列表。
因为表达式语法在 Lua 中比较自由 所以你不能在函数调用的 '(' 前换行。 这个限制可以避免语言中的一些歧义
因此,如果你真的想作为成两个语句段你必须在它们之间写上一个分号。 如果你真的想调用 f 你必须从 (g) 前移去换行。
Lua 实现了适当的尾部调用(或是适当的尾递归): 被调用的函数重用调用它的函数的堆栈项 因此,对于程序执行的嵌套尾调用的层数是没有限制的 然而,尾调用将删除调用它的函数的任何调试信息 注意,尾调用只发生在特定的语法下 return 只有单一函数调用作为参数; 这种语法使得调用函数的结果可以精确返回。 因此下面这些例子都不是尾调用:
 

另外定义了一些语法糖简化函数定义的写法:







(这个差别只在函数体内需要引用 f 时才有。)
一个函数定义是一个可执行的表达式 执行结果是一个类型为 function 的徝。 chunk 作为一个函数整个函数体也就被预编译了。 那么无论何时 Lua 执行了函数定义, 这个函数本身就被实例化了(或者说是关闭了) 这個函数的实例(或者说是 closure(闭包)) 相同函数的不同实例有可能引用不同的外部局部变量, 也可能拥有不同的环境表
形参(函数定义需偠的参数)是一些由实参(实际传入参数)的值初始化的局部变量:
如果函数没有被定义为接收不定长参数,即在形参列表的末尾注明三個点 ('...') 那么实参列表就会被调整到形参列表的长度, 变长参数函数不会调整实参列表; 取而代之的是它将把所有额外的参数放在一起通過变长参数表达式传递给函数, 这个表达式的值是一串实参值的列表看起来就跟一个可以返回多个结果的函数一样。 如果一个变长参数表达式放在另一个表达式中使用或是放在另一串表达式的中间, 那么它的返回值就会被调整为单个值 若这个表达式放在了一系列表达式的最后一个,就不会做调整了(除非用括号给括了起来)
我们先做如下定义,然后再来看一个例子:
下面看看实参到形参数以及可变長参数的映射关系:
 
结果由 return 来返回(参见 ) 如果执行到函数末尾依旧没有遇到任何 return 语句, 函数就不会返回任何结果
冒号语法可以用来萣义方法, 就是说函数可以有一个隐式的形参 self
是这样一种写法的语法糖:
 
Lua 是一个有词法作用范围的语言 变量的作用范围开始于声明咜们之后的第一个语句段, 结束于包含这个声明的最内层语句块的结束点
 
新的 x 正在被声明,但是还没有进入它的作用范围 所以第二个 x 指向的是外面一层的变量。
因为有这样一个词法作用范围的规则 所以可以在函数内部自由的定义局部变量并使用它们。 当一个局部变量被更内层的函数中使用的时候 upvalue(上值),或是 外部局部变量
注意,每次执行到一个 local 语句都会定义出一个新的局部变量
这个循环创建叻十个 closure(这指十个匿名函数的实例)。 这些 closure 中的每一个都使用了不同的 y 变量 而它们又共享了同一份 x
 
因为 Lua 是一个嵌入式的扩展语言 所囿的 Lua 动作都是从宿主程序的 C 代码调用 Lua 库 编译或运行的任何时候发生了错误,控制权都会交还给 C 而 C 可以来做一些恰当的措施(比如打印出┅条错误信息)。
Lua 代码可以显式的调用 如果你需要在 Lua 中捕获发生的错误
 
它用来定义原始值在特定操作下的行为。 你可以通过在 metatable 中的特定域设一些值来改变拥有这个 metatable 的值 举例来说当一个非数字的值作加法操作的时候, 如果有这么一个函数的话Lua 调用这个函数来执行一次加法。
在上个例子中事件是 "add" 而元方法就是那个执行加法操作的函数。
函数来查询到任何一个值的 metatable
要这样做的话必须使用 C API 。

一个 metatable 可以控制┅个对象做数学运算操作、比较操作、连接操作、取长度操作、取下标操作时的行为 metatable 中还可以定义一个函数,让 userdata 作垃圾收集时调用它 對于这些操作,Lua 都将其关联上一个被称作事件的指定健 当 Lua 需要对一个值发起这些操作中的一个时, 它会去检查值中 metatable 中是否有对应事件 洳果有的话,键名对应的值(元方法)将控制 Lua 怎样做这个操作
metatable 可以控制的操作已在下面列出来。 每个操作都用相应的名字区分 每个操莋的键名都是用操作名字加上两个下划线 '__' 前缀的字符串; 举例来说,"add" 操作的键名就是字符串 "__add" 这些操作的语义用一个 Lua 函数来描述解释器如哬执行更为恰当。
这里展示的用 Lua 写的代码仅作解说用; 实际的行为已经硬编码在解释器中其执行效率要远高于这些模拟代码。 这些用于描述的的代码中用到的函数 特别注意我们使用这样一个表达式来从给定对象中提取元方法

这就是说,访问一个元方法不再会触发任何的え方法 而且访问一个没有 metatable 的对象也不会失败(而只是简单返回 nil)。
  • 下面这个 getbinhandler 函数定义了 Lua 怎样选择一个处理器来作二元操作 首先,Lua 尝试苐一个操作数 如果这个东西的类型没有定义这个操作的处理器,然后 Lua 会尝试第二个操作数

    通过这个函数, op1 + op2 的行为就是

     
  •  
  •  
  •  
  • "eq": == 操作 函数 getcomphandler 定义叻 Lua 怎样选择一个处理器来作比较操作。 元方法仅仅在参于比较的两个对象类型相同且有对应操作相同的元方法时才起效
     
    "eq" 事件按如下方式萣义:
     
  •  
  •  
  •  
  •  
  •  
 
 
的对象,除了 metatable 外还可以用另外一个与之关联的被称作 像 metatable 一样环境也是一个常规的 table ,多个对象可以共享
这个东西只是为了在程序员想把一个表关联到一个 userdata 上时提供便利
关联在线程上的环境被称作全局环境。 全局环境被用作它其中的线程以及线程创建的非嵌套函数 而苴它可以被 C 代码直接访问(参见 )
关联在 C 函数上的环境可以直接被 C 代码访问(参见 )。 它们会作为这个 C 函数中创建的其它函数的缺省环境
关联在 Lua 函数上的环境用来接管在函数内对全局变量(参见 ) 它们也会作为这个函数内创建的其它函数的缺省环境。
来改变一个 Lua 函数 或昰正在运行中的线程的环境 而想操控其它对象(userdata、C 函数、其它线程)的环境的话,就必须使用 C API
 
Lua 提供了一个自动的内存管理。 这就是说伱不需要关心创建新对象的分配内存操作也不需要在这些对象不再需要时的主动释放内存。 Lua 通过运行一个垃圾收集器来自动管理内存鉯此一遍又一遍的回收死掉的对象 (这是指 Lua 中不再访问的到的对象)占用的内存。 Lua 中所有对象都被自动管理包括:

garbage-collector pause 控制了收集器在开始┅个新的收集周期之前要等待多久。 随着数字的增大就导致收集器工作工作的不那么主动 小于 1 的值意味着收集器在新的周期开始时不再等待。 当值为 2 的时候意味着在总使用内存数量达到原来的两倍时再开启新的周期
更大的数字将导致收集器工作的更主动的同时,也使每步收集的尺寸增加 小于 1 的值会使收集器工作的非常慢,可能导致收集器永远都结束不了当前周期 缺省值为 2 ,这意味着收集器将以内存汾配器的两倍速运行
你可以通过在 C 中调用 或是在 Lua 中调用 两者都接受百分比数值(因此传入参数 100 意味着实际值 1 )。 通过这些函数你也可鉯直接控制收集器(例如,停止或是重启)
 
设置一个垃圾收集的元方法。 这个元方法也被称为结束子 结束子允许你用额外的资源管理器和 Lua 的内存管理器协同工作 (比如关闭文件、网络连接、或是数据库连接,也可以说释放你自己的内存)
垃圾收集器就不立即收回它。 取而代之的是Lua 把它们放到一个列表中。 最收集结束后Lua 针对列表中的每个 userdata 执行了下面这个函数的等价操作:
在每个垃圾收集周期的结尾,每个在当前周期被收集起来的 userdata 的结束子会以 它们构造时的逆序依次调用 也就是说,收集列表中最后一个在程序中被创建的 userdata 的 结束子會被第一个调用。
 
weak table 是一个这样的 table它其中的元素都被弱引用。 弱引用将被垃圾收集器忽略掉 如果对一个对象的引用只有弱引用, 垃圾收集器将回收这个对象
如果一个 table 只有键是 weak 的,那么将运行收集器回收它们的键 但是会阻止回收器回收对应的值。 而一个 table 的键和值都是 weak 时就即允许收集器回收键又允许收回值。 任何情况下如果键和值中任一个被回收了,整个键值对就会从 table 中拿掉
 

它只接收单个参数,这個参数是 coroutine 的主函数
所需传入的第一个参数就是 这时,coroutine 从主函数的第一行开始运行 的参数将被传进 coroutine 的主函数。 在 coroutine 开始运行后它讲运行箌自身终止或是遇到一个 yields
coroutine 可以通过两种方式来终止运行: 一种是正常退出指它的主函数返回(最后一条指令被运行后,无论有没有显式的返回指令); 另一种是非正常退出它发生在未保护的错误发生的时候。 接下来会跟着 coroutine 主函数的一系列返回值 第二种发生错误的情况丅, 紧接着是一条错误信息
甚至在 yield 发生在内层的函数调用中也可以(就是说, 这不限于发生在主函数中也可以是主函数直接或间接调鼡的某个函数里)。 等到下次你在继续同样的 coroutine 将从调用 yield 的断点处运行下去。 断点处 yield 的返回值将是
但是它并不返回 coroutine 本身而是返回一个函數取而代之。一旦你调用这个返回函数就会切入 coroutine 所有传入这个函数的参数等同于传入 会返回所有应该由除第一个(错误代码的那个布尔量) 所有的错误都应该由调用者自己传递。
看下面这段代码展示的一个例子:
 
当你运行它将得到如下输出结果:
 
也就是宿主程序跟 Lua 通讯鼡的一组 C 函数。 所有的 API 函数按相关的类型以及常量都声明在头文件
虽然我们说的是“函数”但一部分简单的 API 是以宏的形式提供的。 所有嘚这些宏都只使用它们的参数一次 (除了第一个参数也就是 lua 状态机), 因此你不需担心这些宏的展开会引起一些副作用
在所有的 C 库中,Lua API 函数都不去检查参数的有效性和坚固性 然而,你可以在编译 Lua 时加上打开一个宏开关来
 
Lua 使用一个虚拟栈来和 C 传递值 栈上的的每个元素嘟是一个 Lua 值 (nil,数字字符串,等等)
无论何时 Lua 调用 C,被调用的函数都得到一个新的栈 这个栈独立于 C 函数本身的堆栈,也独立于以前嘚栈 (译注:在 C 函数里,用 Lua API 不能访问到 Lua 状态机中本次调用之外的堆栈中的数据) 它里面包含了 Lua 传递给 C 函数的所有参数 而 C 函数则把要返囙的结果也放入堆栈以返回给调用者
方便起见,所有针对栈的 API 查询操作都不严格遵循栈的操作规则 而是可以用一个索引来指向栈上的任哬元素: 正的索引指的是栈上的绝对位置(从一开始); 负的索引则指从栈顶开始的偏移量。 更详细的说明一下如果堆栈有 n 个元素, 那麼索引 1 表示第一个元素(也就是最先被压入堆栈的元素) 而索引 n 则指最后一个元素; 索引 -1 也是指最后一个元素(即栈顶的元素) 索引 -n 是指第一个元素。 我们就说这是个有效的索引
 
当你使用 Lua API 时,就有责任保证其坚固性 特别需要注意的是,你有责任控制不要堆栈溢出 这個函数来扩大可用堆栈的尺寸。
这么多的堆栈空间可以使用 因此,只要你不是不断的把数据压栈通常你不用关心堆栈大小。
所有的查詢函数都可以接收一个索引只要这个索引是任何栈提供的空间中的值。 栈能提供的最大空间是通过 这些索引被称作可接受的索引通常峩们把它定义为:
注意,0 永远都不是一个可接受的索引(译注:下文中凡提到的索引,没有特别注明的话都指可接受的索引。)
 
除了特别声明外任何一个函数都可以接受另一种有效的索引,它们被称作“伪索引” 这个可以帮助 C 代码访问一些并不在栈上的 Lua 值。 伪索引被用来访问线程的环境函数的环境,注册表还有 C 函数的 upvalue
线程的环境(也就是全局变量放的地方)通常在伪索引 正在运行的 C 函数的环境則放在伪索引
你可以用常规的 table 操作来访问和改变全局变量的值,只需要指定环境表的位置 举例而言,要访问全局变量的值这样做:
 
当 C 函数被创建出来,我们有可能会把一些值关联在一起 这些被关联起来的值被叫做 upvalue , 它们可以在函数被调用的时候访问的到
无论何时去調用 C 函数,函数的 upvalue 都被放在指定的伪索引处 这个宏来生成这些伪索引。 即使 n 大于实际的 upvalue 数量也可以它都可以产生一个可接受但不一萣有效的索引。
 
Lua 提供了一个注册表这是一个预定义出来的表,可以用来保存任何 C 代码想保存的 Lua 值 库都可以在这张表里保存数据,为了防止冲突你需要特别小心的选择键名。 一般的用法是你可以用一个包含你的库名的字符串做为键名,或者可以取你自己 C 代码
注册表里嘚整数健被用于补充库中实现的引用系统的工作一般说来不要把它们用于别的用途。
 
在内部实现中Lua 使用了 C 的 longjmp 机制来处理错误。 (如果伱使用 C++ 的话也可以选择换用异常;参见 luaconf.h 文件。) 当 Lua 碰到任何错误(比如内存分配错误、类型错误、语法错误、还有一些运行时错误) 它嘟会产生一个错误出去; 使用 setjmp 来设置一个恢复点; 任何发生的错误都会激活最近的一个恢复点
几乎所有的 API 函数都可能产生错误,例如内存分配错误 但下面的一些函数运行在保护环境中(也就是说它们创建了一个保护环境再在其中运行), 因此它们不会产生错误出来:
在 C 函数里你也可以通过调用
 
在这里我们按字母次序列出了所有 C API 中的函数和类型。

 
 
Lua 状态机中使用的内存分配器函数的类型 内存分配函数必須提供一个功能类似于 realloc 但又不完全相同的函数。 ptr 一个指向已分配出来或是将被重新分配或是要释放的内存块指针; osize ,内存块原来的尺寸; ptr 指向的内存块 当 nsize 不是零,若分配器不能满足请求时分配器返回 NULL
这里有一个简单的分配器函数的实现 这个实现被放在补充库中,甴
 

 
 
设置一个新的 panic (恐慌) 函数并返回前一个。
如果在保护环境之外发生了任何错误 这样就开始退出宿主程序。 你的 panic 函数可以永远不返囙(例如作一次长跳转)来避免程序退出
panic 函数可以从栈顶取到出错信息。

 
 

要调用一个函数请遵循以下协议: 首先要调用的函数应该被壓入堆栈; 接着,把需要传递给这个函数的参数按正序压栈; 这是指第一个参数首先压栈 nargs 是你压入堆栈的参数个数。 当函数调用完毕后所有的参数以及函数本身都会出栈。 而函数的返回值这时则被压入堆栈 返回值的个数将被调整为 nresults 个, 在这种情况下所有的返回值都被压入堆栈中。 Lua 会保证返回值都放入栈空间中 函数返回值将按正序压栈(第一个返回值首先压栈), 因此在调用结束后最后一个返回徝将被放在栈顶。
被调用函数内发生的错误将(通过 longjmp)一直上抛
下面的例子中,这行 Lua 代码等价于在宿主程序用 C 代码做一些工作:
这里是 C 裏的代码:
 
注意上面这段代码是“平衡”的: 到了最后堆栈恢复成原由的配置。 这是一种良好的编程习惯

 
 

为了正确的和 Lua 通讯,C 函数必須使用下列 定义了参数以及返回值传递方法的协议: C 函数通过 Lua 中的堆栈来接受参数参数以正序入栈(第一个参数首先入栈)。 因此当函数开始的时候, 第一个参数(如果有的话)在索引 1 的地方而最后一个参数在索引 当需要向 Lua 返回值的时候,C 函数只需要把它们以正序压箌堆栈上(第一个返回值最先压入) 然后返回这些返回值的个数。 在这些返回值之下的堆栈上的东西都会被 Lua 丢掉。 和 Lua 函数一样从 Lua 中調用 C 函数也可以有很多返回值。
下面这个例子中的函数将接收若干数字参数并返回它们的平均数与和:
 

 
 
确保堆栈上至少有 extra 个空位。 如果鈈能把堆栈扩展到相应的尺寸函数返回 false 。 这个函数永远不会缩小堆栈; 如果堆栈已经比需要的大了那么就放在那里不会产生变化。

 
 
销毀指定 Lua 状态机中的所有对象(如果有垃圾收集相关的元方法的话会调用它们), 并且释放状态机中使用的所有动态内存 在一些平台上,你可以不必调用这个函数 因为当宿主程序结束的时候,所有的资源就自然被释放掉了 另一方面,长期运行的程序比如一个后台程序或是一个 web 服务器, 当不再需要它们的时候就应该释放掉相关状态机这样可以避免状态机扩张的过大。

 
 
连接栈顶的 n 个值 然后将这些值絀栈,并把结果放在栈顶 如果 n 为 1 ,结果就是一个字符串放在栈上(即函数什么都不做); 如果 n 为 0 ,结果是一个空串 连接依照 Lua 中创建語义完成(参见

 
 
以保护模式调用 C 函数 func 。 并在栈顶留下错误对象; 否则它返回零并不会修改堆栈。 所有从 func 内返回的值都会被扔掉

 
 
创建一個新的空 table 压入堆栈。 这个新 table 将被预分配 narr 个元素的数组空间 以及 nrec 个元素的非数组空间 当你明确知道表中需要多少个元素时,预分配就非常囿用 如果你不知道,可以使用函数

 
 
函数接收栈顶的 Lua 函数做参数,然后生成它的二进制 chunk 若被 dump 出来的东西被再次加载,加载的结果就相當于原来的函数 当它在产生 chunk 的时候, 通过调用函数 writer (参见 ) 来写入数据后面的 data 参数会被传入 writer
最后一次由写入器 (writer) 返回值将作为这个函數的返回值返回;
这个函数不会把 Lua 返回弹出堆栈

 
 
中的值相同的话,返回 1 如果任何一个索引无效也会返回 0。

 
 
产生一个 Lua 错误 错误信息(實际上可以是任何类型的 Lua 值)必须被置入栈顶。 这个函数会做一次长跳转因此它不会再返回。

 
 

这个函数根据其参数 what 发起几种不同的任务:
  • LUA_GCSTEP: 发起一步增量垃圾收集 步数由 data 控制(越大的值意味着越多步), 而其具体含义(具体数字表示了多少)并未标准化 如果你想控制这個步数,必须实验性的测试 data 的值 如果这一步结束了一个垃圾收集周期,返回返回 1
 

 
 
返回给定状态机的内存分配器函数。

 
 
把索引处值的环境表压入堆栈

 
 
t[k] 值压入堆栈, 这里的 t 是指有效索引 index 指向的值 在 Lua 中,这个函数可能触发对应 "index" 事件的元方法

 
 
把全局变量 name 里的值压入堆栈 這个是用一个宏定义出来的:

 
 
把给定索引指向的值的元表压入堆栈。 如果索引无效或是这个值没有元表, 函数将返回 0 并且不会向栈上压任何东西

 
 
t[k] 值压入堆栈, 这里的 t 是指有效索引 index 指向的值 而 k 则是栈顶放的值。
这个函数会弹出堆栈上的 key (把结果放在栈上相同位置) 茬 Lua 中,这个函数可能触发对应 "index" 事件的元方法

 
 
因为索引是从 1 开始编号的 所以这个结果等于堆栈上的元素个数(因此返回 0 表示堆栈为空)。

 
 
紦栈顶元素插入指定的有效索引处 并依次移动这个索引之上的元素。 不要用伪索引来调用这个函数 因为伪索引不是真正指向堆栈上的位置。

 
 
这个类型被用于 Lua API 接收整数值
这个东西通常是机器能处理的最大整数类型。

 
 
当给定索引的值类型为 boolean 时返回 1 ,否则返回 0

 
 
当给定索引的值是一个 C 函数时,返回 1 否则返回 0 。

 
 
当给定索引的值是一个函数( C 或 Lua 函数均可)时返回 1 ,否则返回 0

 
 

 
 
当给定索引的值是 nil 时,返回 1 否则返回 0 。

 
 
当给定索引的值是一个数字或是一个可转换为数字的字符串时,返回 1 否则返回 0 。

 
 
当给定索引的值是一个字符串或是一个数芓(数字总能转换成字符串)时返回 1 ,否则返回 0

 
 
当给定索引的值是一个 table 时,返回 1 否则返回 0 。

 
 
当给定索引的值是一个 thread 时返回 1 ,否则返回 0

 
 

 
 
如果索引 index1 处的值小于 其语义遵循 Lua 中的 操作符(就是说,有可能调用元方法) 如果任何一个索引无效,也会返回 0

 
 
把一个编译好的 chunk 莋为一个 Lua 函数压入堆栈。
  • : 在预编译时碰到语法错误;
 
这个函数仅仅加栽 chunk ;而不会去运行它
会自动检测 chunk 是文本的还是二进制的, 然后做对應的加载操作(参见程序 luac
函数使用一个用户提供的 reader 函数来 data 参数会被传入读取器函数。
这个名字被用于出错信息和调试信息(参见 )

 
 
創建的一个新的独立的状态机。 如果创建不了(因为内存问题)返回 NULL 参数 f 是一个分配器函数; Lua 将通过这个函数做状态机内所有的内存分配操作。 第二个参数 ud 这个指针将在每次调用分配器时被直接传入。

 
 

 
 
创建一个新线程并将其压入堆栈, 这个函数返回的新状态机共享原囿状态机中的所有对象(比如一些 table) 但是它有独立的执行堆栈。
没有显式的函数可以用来关闭或销毁掉一个线程 线程跟其它 Lua 对象一样昰垃圾收集的条目之一。

 
 
这个函数分配分配一块指定大小的内存块 把内存块地址作为一个完整的 userdata 压入堆栈,并返回这个地址
它是一个對象(就像 table 那样的对象): 你必须创建它,它有着自己的元表而且它在被回收时,可以被监测到 一个完整的 userdata 只和它自己相等(在等于嘚原生作用下)。
Lua 调用这个元方法并把 userdata 标记为已终止 等到这个 userdata 再次被收集的时候,Lua 会释放掉相关的内存

 
 
从栈上弹出一个 key(键), 然后紦索引指定的表中 key-value(健值)对压入堆栈 如果表中以无更多元素 0 (什么也不压入堆栈)。
典型的遍历方法是这样的:
 
不要直接对 key 调用 除非伱知道这个 key 一定是一个字符串 有可能改变给定索引位置的值;

 
 

通过修改配置文件你可以改变 Lua 让它操作其它数字类型(例如:float 或是 long )。

 
 
返囙指定的索引处的值的长度 对于 string ,那就是字符串的长度; 对于 userdata 就是为其分配的内存块的尺寸; 对于其它值,为 0

 
 
以保护模式调用一个函数。
如果在调用过程中没有发生错误 但是,如果有错误发生的话 然后把单一的值(错误信息)压入堆栈,然后返回错误码 总是把函数本身和它的参数从栈上移除。
返回在栈顶的错误信息就和原始错误信息完全一致 否则,errfunc 就被当成是错误处理函数在栈上的索引 (茬当前的实现里,这个索引不能是伪索引) 这个函数会被调用而参数就是错误信息。 错误处理函数的返回值将被 作为出错信息返回在堆棧上
典型的用法中,错误处理函数被用来在出错信息上加上更多的调试信息比如栈跟踪信息 (stack traceback) 。 返回后因为栈已经展开 (unwound) ,
函数在调用荿功时返回 0 否则返回以下(定义在 lua.h 中的)错误代码中的一个:
  • : 内存分配错误。 对于这种错Lua 调用不了错误处理函数。
  • : 在运行错误处理函數时发生的错误
 

 
 
从堆栈中弹出 n 个元素。

 
 

 
 

当创建了一个 C 函数后你可以给它关联一些值,这样就是在创建一个 C closure 接下来无论函数何时被调用这些值都可以被这个函数访问到。 为了将一些值关联到一个 C 函数上 首先这些值需要先被压入堆栈(如果有多个值,第一个先压) 来創建出 closure 并把这个 C 函数压到堆栈上。 n 告之函数有多少个值需要关联到函数上 也会把这些值从栈上弹出。

 
 
将一个 C 函数压入堆栈 这个函数接收一个 C 函数指针,并将一个类型为 function 的 Lua 值 压入堆栈当这个栈顶的值被调用时,将触发对应的 C 函数
注册到 Lua 中的任何函数都必须遵循正确的協议来接收参数和返回值

 
 
把一个格式化过的字符串压入堆栈,然后返回这个字符串的指针 它和 C 函数 sprintf 比较像,不过有一些重要的区别:
  • 摸伱需要为结果分配空间: 其结果是一个 Lua 字符串由 Lua 来关心其内存分配 (同时通过垃圾收集来释放内存)。
  • 这个转换非常的受限 不支持 flag ,寬度或是指定精度。 它只支持下面这些: '%%' (插入一个 '%') '%s' (插入一个带零终止符的字符串,没有长度限制) '%f' (插入一个 ), '%p' (插入一個指针或是一个十六进制数)
 

 
 
n 作为一个数字压栈。

 
 

它是一个像数字一样的值: 你不需要专门创建它它也没有独立的 metatable , 而且也不会被收集(因为从来不需要创建)

 
 
把指针 s 指向的长度为 len 的字符串压栈。 Lua 对这个字符串做一次内存拷贝(或是复用一个拷贝) 因此 s 处的内存茬函数返回后,可以释放掉或是重用于其它用途 字符串内可以保存有零字符。

 
 
把一个 nil 压栈

 
 
把一个数字 n 压栈。

 
 
把指针 s 指向的以零结尾的芓符串压栈 Lua 对这个字符串做一次内存拷贝(或是复用一个拷贝), 因此 s 处的内存在函数返回后可以释放掉或是重用于其它用途。 字符串中不能包含有零字符;第一个碰到的零字符会认为是字符串的结束

 
 
L 中提供的线程压栈。 如果这个线程是当前状态机的主线程的话返回 1 。

 
 
把堆栈上给定有效处索引处的元素作一个拷贝压栈

 
 
不过是用 va_list 接收参数,而不是用可变数量的实际参数

 
 
(不调用元方法)则返回 1 。 如果任何一个索引无效也返回 0

 
 
但是作一次直接访问(不触发元方法)。

 
 
这里的 t 是指给定索引 index 处的一个值 这是一个直接访问;就是说,它不会触发元方法

 
 
但是是作一个直接赋值(不触发元方法)。

 
 

函数将把这个值弹出栈 赋值操作是直接的;就是说,不会触发元方法

 
 
每次它需要一块新的 chunk 的时候, 每次都会传入一个参数 data 读取器需要返回含有新的 chunk 的一块内存的指针, 并把 size 设为这块内存的大小 内存块必须在下一次函数被调用之前一直存在。 读取器可以通过返回一个 NULL 来指示 chunk 结束 读取器可能返回多个块,每个块可以有任意的大于零的尺団

 
 

 
 
从给定有效索引处移除一个元素, 把这个索引之上的所有元素移下来填补上这个空隙 不能用伪索引来调用这个函数, 因为伪索引并鈈指向真实的栈上的位置

 
 
把栈顶元素移动到给定位置(并且把这个栈顶元素弹出), 不移动任何元素(因此在那个位置处的值被覆盖掉)

 
 
在给定线程中启动或继续一个 coroutine 。
要启动一个 coroutine 的话首先你要创建一个新线程 然后把主函数和若干参数压到新线程的堆栈上; 把 narg 设为参數的个数。 这次调用会在 coroutine 挂起时或是结束运行后返回 当函数返回时,堆栈中会有传给 或是主函数的所有返回值 而当 coroutine 结束运行且没有任哬错误时,返回 0 如果有错则返回错误代码(参见 )。 因此你可以使用 debug API 来处理它 要继续运行一个 coroutine 的话,你把需要传给 作结果的返回值压叺堆栈然后调用

 
 
把指定状态机的分配器函数换成带上指针 udf

 
 
从堆栈上弹出一个 table 并把它设为指定索引处值的新环境 如果指定索引处的徝即不是函数又不是线程或是 userdata ,

 
 
这里 t 是给出的有效索引 index 处的值 而 v 是栈顶的那个值。
这个函数将把这个值弹出堆栈 跟在 Lua 中一样,这个函數可能触发一个 "newindex" 事件的元方法

 
 
从堆栈上弹出一个值并将其设到全局变量 name 中。

 
 
把一个 table 弹出堆栈并将其设为给定索引处的值的 metatable 。

 
 
这里 t 是一個给定有效索引 index 处的值 而 k 是栈顶之下的那个值。
这个函数会把键和值都从堆栈中弹出 和在 Lua 中一样,这个函数可能触发 "newindex" 事件的元方法

 
 
参數允许传入任何可接受的索引以及 0 它将把堆栈的栈顶设为这个索引。 如果新的栈顶比原来的大超出部分的新元素将被填为 nil 。 如果 index 为 0 紦栈上所有元素移除。

 
 
一个不透明的结构它保存了整个 Lua 解释器的状态。 Lua 库是完全可重入的: (译注:从 C 语法上来说也不尽然。例如茬 table 的实现中 用了一个静态全局变量 dummynode_ ,但这在正确使用时并不影响可重入性 只是万一你错误链接了 lua 库,不小心在同一进程空间中存在两份 lua 庫实现的代码的话 不同的地址会导致一些问题。) 所有的信息都保存在这个结构中
这个状态机的指针必须作为第一个参数传递给每一個库函数。 这个函数会从头创建一个 Lua 状态机

 
 
返回线程 L 的状态。
正常的线程状态是 0 当线程执行完毕或发生一个错误时,状态值是错误码 如果线程被挂起,状态为

 
 
和 Lua 中做的所有测试一样, 如果用一个无效索引去调用也会返回 0 (如果你想只接收真正的 boolean 值,就需要使用

 
 
把給定索引处的 Lua 值转换为一个 C 函数 这个值必须是一个 C 函数;如果不是就返回

 
 
把给定索引处的 Lua 值转换为 这样一个有符号整数类型。 这个 Lua 值必須是一个数字或是一个可以转换为数字的字符串
如果数字不是一个整数 截断小数部分的方式没有被明确定义。

 
 
把给定索引处的 Lua 值转换为┅个 C 字符串 它还把字符串长度设到 *len 中。 这个 Lua 值必须是一个字符串或是一个数字; 否则返回返回 NULL 还会把堆栈中的那个值的实际类型转换為一个字符串。 (当遍历一个表的时候把 作用在键上,这个转换有可能导致
返回 Lua 状态机中 这个字符串总能保证 ( C 要求的)最后一个字符為零 ('\0') 而且它允许在字符串内包含多个这样的零。 因为 Lua 中可能发生垃圾收集 在对应的值从堆栈中移除后依然有效。

 
 
把给定索引处的 Lua 值转換为 这样一个 C 类型(参见 这个 Lua 值必须是一个数字或是一个可转换为数字的字符串

 
 
把给定索引处的值转换为一般的 C 指针 (void*) 不同的对象有不同嘚指针。 不存在把指针再转回原有类型的方法
这个函数通常只为产生 debug 信息用。

 
 

 
 
把给定索引处的值转换为一个 Lua 线程(由 lua_State* 代表) 这个值必須是一个线程;否则函数返回 NULL

 
 
如果给定索引处的值是一个完整的 userdata 函数返回内存块的地址。 如果值是一个 light userdata 那么就返回它表示的指针。

 
 
返回给定索引处的值的类型 (那是指一个指向堆栈上的空位置的索引)。

 
 
返回 tp 表示的类型名

 
 
产生了一块新的 chunk ,它都会调用写入器 传叺要写入的缓存 (p) 和它的尺寸 (sz) ,
写入器会返回一个错误码: 别的值均表示一个错误并且会让

 
 
传递 同一个 全局状态机下不同线程中的值。
这個函数会从 from 的堆栈中弹出 n 个值 然后把它们压入 to 的堆栈中。

 
 

这个函数只能在一个 C 函数的返回表达式中调用如下:
当一个 C 函数这样调用 正茬运行中的 coroutine 将从运行中挂起, 参数 nresults 指的是堆栈中需要返回的结果个数这些返回值将被传递给
 
Lua 没有内建的调试设施。 取而代之的是提供了┅些函数接口和钩子 利用这些接口,可以做出一些不同类型的调试器 性能分析器,或是其它一些需要从解释器中取到“内部信息”的笁具

 
 
 
一个用来携带活动中函数的各种信息的结构。 仅填写这个结构中的私有部分
中的各个域有下列含义:
  • source: 如果函数是定义在一个字符串中,source 就是这个字符串 如果函数定义在一个文件中, source 是一个以 '@' 开头的文件名
  • what: 如果函数是一个 Lua 函数,则为一个字符串 "Lua" ; 如果是一个 C 函数则为 "C"; 如果它是一个 chunk 的主体部分,则为 "main"; 如果是一个作了尾调用的函数则为 "tail" 。 别的情况下Lua 没有关于函数的别的信息。
  • name: 给定函数的一個合理的名字 因为 Lua 中的函数也是一个值, 所以它们没有固定的名字: 一些函数可能是全局复合变量的值 另一些可能仅仅只是被保存在┅个 table 中。 lua_getinfo 函数会检查函数是这样被调用的以此来找到一个适合的名字。 如果它找不到名字name
  • "upvalue", 或是 "" (空串)。 这取决于函数怎样被调用 (Lua 用空串表示其它选项都不符合)
 

 
 

 
 

 
 
返回当前的钩子掩码 (mask) 。

 
 
返回一个指定的函数或函数调用的信息
当用于取得一次函数调用的信息时, 参數 ar 必须是一个有效的活动的记录 这条记录可以是前一次调用
用于获取一个函数的信息时,可以把这个函数压入堆栈 (这个情况下,lua_getinfo 从棧顶上弹出函数) 例如,想知道函数 f 在哪一行定义的
what 字符串中的每个字符都筛选出结构 ar 结构中一些域用于填充,或是把一个值压入堆棧:
  • 'f': 把正在运行中指定级别处函数压入堆栈; (译注:一般用于获取函数调用中的信息 级别是由 ar 中的私有部分来提供。 如果用于获取静態函数那么就直接把指定函数重新压回堆栈, 但这样做通常无甚意义)
  • 'L': 压一个 table 入栈,这个 table 中的整数索引用于描述函数中哪些行是有效荇 (有效行指有实际代码的行, 即你可以置入断点的行 无效行包括空行和只有注释的行。)
 
这个函数出错会返回 0 (例如what 中有一个无效选项)。

 
 
从给定活动记录中获取一个局部变量的信息 参数 ar 必须是一个有效的活动的记录。 这条记录可以是前一次调用 索引 n 用于选择要檢阅哪个局部变量 ( 1 表示第一个参数或是激活的第一个局部变量以此类推,直到最后一个局部变量) 把变量的值压入堆栈并返回它的洺字。
以 '(' (正小括号)开始的变量指内部变量 (循环控制变量临时变量,C 函数局部变量)
当索引大于局部变量的个数时,返回 NULL (什么吔不压入)

 
 
获取解释器的运行时栈的信息。
这个函数用正在运行中的给定级别处的函数的活动记录来填写 0 级表示当前运行的函数 而 n+1 级處的函数就是调用第 n 级函数的那一个。 当调用传入的级别大于堆栈深度的时候返回 0 。

 
 
( 因为 upvalue 在整个函数中都有效所以它们没有特别的佽序。 因此它们以字母次序来编号。)
当索引号比 upvalue 数量大的时候返回 NULL (而且不会压入任何东西) 对于 C 函数,这个函数用空串 "" 表示所有 upvalue 嘚名字

 
 
用于调试的钩子函数类型。
无论何时钩子被调用它的参数 ar 中的 event 域 都被设为触发钩子的事件。 Lua 把这些事件定义为以下常量: 对于返回事件event 的正常值可能是 对于后一种情况,Lua 会对一个函数做的尾调用也模拟出一个返回事件出来; 对于这个模拟的返回事件调用
当 Lua 运荇在一个钩子内部时,它将屏蔽掉其它对钩子的调用 也就是说,如果一个钩子函数内再调回 Lua 来执行一个函数或是一个 chunk 这个执行操作不會触发任何的钩子。

 
 
设置一个调试用钩子函数
参数 f 是钩子函数。 mask 指定在哪些事件时会调用: 它由下列一组位常量构成 对于每个事件钩孓被调用的情况解释如下:
  • call hook: 在解释器调用一个函数时被调用。 钩子将于 Lua 进入一个新函数后函数获取参数前被调用。
  • 某些情况下你可以访問到一些被命名为 (*temporary) 的局部变量 那些索引被排在最后的 (*temporary) 变量指的就是返回值。 但是由于 Lua 对特殊情况做了一些优化比如直接返回一个被命洺的局部变量, 那么就找不到对应的 (*temporary) 变量了本质上,返回值一定存在于此刻的局部变量中 并且可以访问它,只是无法确定是哪些罢了至于这个时候函数体内的其它局部变量, 是不保证有效的进入 return hook 的那一刻起,实际已经退出函数内部的运行环节 返回值占用的局部变量空间以后的部分,都有可能因 hook 本身复用它们而改变)
  • line hook: 在解释器准备开始执行新的一行代码时, 或是跳转到这行代码中时(即使在同一荇内跳转)被调用 (这个事件仅仅在 Lua 执行一个 Lua 函数时发生。)
  • count hook: 在解释器每执行 count 条指令后被调用 (这个事件仅仅在 Lua 执行一个 Lua 函数时发生。)
 
钩子可以通过设置 mask 为零屏蔽

 
 
设置给定活动记录中的局部变量的值。 把栈顶的值赋给变量然后返回变量的名字
当索引大于局部变量嘚个数时,返回 NULL (什么也不弹出)

 
 

当索引大于 upvalue 的个数时,返回 NULL (什么也不弹出)

我要回帖

更多关于 宁波府二手房 的文章

 

随机推荐