Lua系列文章(1)---Lua5.4参考手册学习总结

windows系统上安装lua,下载地址:

Github 下载地址:https://github.com/rjpcomputing/luaforwindows/releases

可以有一个叫SciTE的IDE环境执行lua程序

Lua系列文章(1)---Lua5.4参考手册学习总结_第1张图片

1 – 简介

Lua 是一种强大、高效、轻量级、可嵌入的脚本语言。 它支持过程编程, 面向对象编程、函数式编程、 数据驱动的编程和数据描述。

Lua 基于关联数组和可扩展语义的构造,将简单的过程语法与强大的数据描述相结合 。 Lua 是动态类型的, 通过使用基于寄存器的解释字节码来运行 虚拟机 并具有自动内存管理 代际垃圾收集, 使其成为理想的配置、脚本、 和快速原型开发的语言。

Lua被实现为一个库,用干净的C编写, 标准 C 和 C++ 的常见子集。 Lua 发行版包含一个名为lua 的主机程序, 它使用 Lua 库来提供完整的、 独立的Lua解释器luac.exe, 用于交互式或批量使用。 Lua旨在用作强大,轻量级, 可嵌入的脚本语言,适用于任何需要的程序, 并作为一种功能强大但轻量级且高效的独立语言。lua作为一种扩展语言,没有“主”程序的概念: 它嵌入在主机客户端中工作, 称为嵌入程序或简称为主机。 (通常,此主机是独立程序lua.exe)。

Lua系列文章(1)---Lua5.4参考手册学习总结_第2张图片

宿主程序可以调用函数来执行一段 Lua 代码, 可以写入和读取Lua变量, 并且可以注册要由Lua代码调用的C函数。 通过使用 C 函数,Lua 可以增强以应对 广泛的不同领域, 从而创建共享语法框架的自定义编程语言。

2 – 基本概念

2.1 – 值和类型

Lua 是一种动态类型语言。 这意味着 变量没有类型;只有值可以。 该语言中没有类型定义。 所有值都有自己的类型。

Lua 中的所有值都是一等值。 这意味着所有值都可以存储在变量中, 作为参数传递给其他函数,并作为结果返回。

Lua 中有八种基本类型:nil布尔值数字字符串函数用户数据线程。 类型 nil 有一个值 nil, 其主要属性与任何其他值不同; 它通常表示缺少有用的值。 布尔值类型有两个值:false 和 true。 “”和“假”都使条件为假; 它们统称为假值。 任何其他值都会使条件为真。 尽管它的名字,false 经常被用作 nil 的替代品, 与错误行为的关键区别 就像表中的常规值一样, 而表中的 nil 表示缺少键。

类型编号表示两者 整数和实数(浮点数), 使用两个子类型:整数浮点数。 标准 Lua 使用 64 位整数和双精度(64 位)浮点数, 但你也可以编译Lua,让它 使用 32 位整数和/或单精度(32 位)浮点数。 具有 32 位的整数和浮点数选项 特别有吸引力 适用于小型机器和嵌入式系统。 (请参阅文件中的宏。LUA_32BITSluaconf.h

除非另有说明, 操作整数值时的任何溢出都会环绕, 根据二进制补码算术的通常规则。 (换句话说, 实际结果是唯一的可表示整数 等于数学结果的模 2n, 其中 n 是整数类型的位数。

Lua 对何时使用每个子类型有明确的规则, 但它也会根据需要在它们之间自动转换(参见 §3.4.3)。 因此 程序员可能会选择忽略差异 在整数和浮点数之间 或者完全控制每个数字的表示形式。

字符串类型表示不可变的字节序列。 Lua 是 8 位干净的: 字符串可以包含任何 8 位值, 包括嵌入的零 ('')。 Lua 也是与编码无关的; 它不对字符串的内容做出任何假设。 Lua 中任何字符串的长度都必须适合 Lua 整数。\0

Lua 可以调用(和操作)用 Lua 编写的函数和 用 C 语言编写的函数(参见 §3.4.10)。 两者都由类型函数表示。

提供用户数据类型以允许任意 C 数据 存储在 Lua 变量中。 用户数据值表示原始内存块。 有两种类型的用户数据:完整的用户数据, 这是一个具有由Lua管理的内存块的对象, 和轻用户数据, 它只是一个 C 指针值。 用户数据在 Lua 中没有预定义的操作, 除了分配和身份测试。 通过使用元表, 程序员可以为完整的用户数据值定义操作 (见§2.4)。 无法在 Lua 中创建或修改用户数据值, 只能通过 C API。 这保证了拥有的数据的完整性 主机程序和 C 库。

线程类型表示独立的执行线程 它用于实现协程(参见 §2.6)。 Lua 线程与操作系统线程无关。 Lua 支持所有系统上的协程, 即使是那些本身不支持线程的线程。

类型实现关联数组, 也就是说,数组不仅可以将数字作为索引, 但除 nil 和 NaN 之外的任何 Lua 值。 (不是数字是一个特殊的浮点值 由 IEEE 754 标准用于表示 未定义的数值结果,例如 .) 表可以是异构的; 也就是说,它们可以包含所有类型的值(Nil 除外)。 与值 nil 关联的任何键都不被视为表的一部分。 相反,不属于表的任何键都具有 关联的值 nil0/0

表是 Lua 中唯一的数据结构化机制; 它们可用于表示普通数组、列表、 符号表、集合、记录、图形、树等。 为了表示记录,Lua 使用字段名称作为索引。 该语言通过以下方式支持此表示形式 提供作为句法糖 的 。 有几种方便的方法可以在 Lua 中创建表 (参见 §3.4.9)。a.namea["name"]

像指数一样, 表字段的值可以是任何类型。 特别 因为函数是一等值, 表字段可以包含函数。 因此,表也可以携带方法(参见§3.4.11)。

表的索引如下 语言中原始平等的定义。 表达式和表示相同的表元素 当且仅当 和 是原始相等的 (即,在没有元方法的情况下相等)。 特别是具有整数值的浮点数 等于它们各自的整数 (例如,)。 为避免歧义, 用作等于整数的键的任何浮点数 将转换为该整数。 例如,如果你写 , 插入到表中的实际键将是整数。a[i]a[j]ij1.0 == 1a[2.0] = true2

表、函数、线程和(完整)用户数据值是对象: 变量实际上不包含这些值, 仅引用它们。 赋值、参数传递和函数返回 始终操纵对此类值的引用; 这些操作并不意味着任何类型的副本。

库函数类型返回描述类型的字符串 给定值(请参阅类型)。

2.2 – 环境与全局环境

正如我们将在 §3.2 和 §3.3.3 中进一步讨论的, 对自由名称的任何引用 (即,不绑定到任何声明的名称)在语法上转换为 。 此外,每个块都是在 名为(参见 §3.3.2)的外部局部变量, 所以它本身从来都不是一个块中的自由名称。var_ENV.var_ENV_ENV

尽管存在这个外部变量和 自由名称的翻译,是一个完全常规的名称。 特别 您可以使用该名称定义新的变量和参数。 对自由名称的每个引用都使用 在程序中的该点可见, 遵循 Lua 通常的可见性规则(参见 §3.5)。_ENV_ENV_ENV

用作 值的任何表都称为环境_ENV

Lua保留了一个称为全球环境的杰出环境。 该值保存在 C 注册表中的特殊索引中(参见 §4.3)。 在 Lua 中,全局变量 _G 使用相同的值进行初始化。 (_G从不内部使用, 因此,更改其值只会影响您自己的代码。

当 Lua 加载一个块时, 其变量的默认值 是全局环境(请参阅加载)。 因此,默认情况下, Lua 代码中的自由名称是指全局环境中的条目 因此,它们也被称为全局变量。 此外,所有标准库都加载在全局环境中 那里的某些功能在该环境中运行。 您可以使用加载(或加载文件) 以加载具有不同环境的区块。 (在 C 中,您必须加载块,然后更改值 其首次升值;请参阅lua_setupvalue。_ENV

2.3 – 错误处理

Lua 中的多个操作可能会引发错误。 错误中断程序的正常流程, 可以通过捕获错误来继续。

Lua 代码可以通过调用错误函数来显式引发错误。 (此函数从不返回。

要捕获 Lua 中的错误, 您可以进行受保护的呼叫, 使用 pcall(或 XPCALL)。 函数 pcall 在保护模式下调用给定函数。 运行函数时出现的任何错误都会停止其执行, 并且控制立即返回到 , 返回状态代码。pcall

因为Lua是一种嵌入式扩展语言, Lua 代码通过调用开始运行 从主机程序中的 C 代码。 (当您单独使用 Lua 时, 应用程序是主机程序。 通常,此调用受到保护; 因此,当在以下过程中发生其他不受保护的错误时 Lua 块的编译或执行, 控制权返回主机, 可以采取适当措施, 例如打印错误消息。lua

每当出现错误时, 使用有关错误的信息传播错误对象。 Lua 本身只生成错误对象为字符串的错误, 但是程序可能会产生错误 任何值作为错误对象。 由Lua程序或其主机来处理此类错误对象。 由于历史原因, 错误对象通常称为错误消息, 即使它不必是字符串。

当您使用 xpcall(或 lua_pcall,在 C 中)时 您可以提供一个在发生错误时调用的消息处理程序。 此函数使用原始错误对象调用 并返回一个新的错误对象。 在错误展开堆栈之前调用它, 以便它可以收集有关错误的更多信息, 例如,通过检查堆栈并创建堆栈回溯。 此消息处理程序仍受受保护调用的保护; 因此,消息处理程序中的错误 将再次调用消息处理程序。 如果这个循环持续太久, Lua 会破坏它并返回相应的消息。 仅针对常规运行时错误调用消息处理程序。 内存分配错误不调用 也不用于运行终结器或其他消息处理程序时的错误。

Lua还提供了一个警告系统(见警告)。 与错误不同,警告不会干扰 以任何方式执行程序。 它们通常只生成一条消息给用户, 尽管此行为可以从 C 改编(参见lua_setwarnf)。

2.4 – 元表和元方法

Lua 中的每个值都可以有一个元表。 此元表是一个普通的 Lua 表 定义原始值的行为 在某些事件下。 您可以更改行为的多个方面 通过在其元表中设置特定字段来定义值。 例如,当非数值是加法的操作数时, Lua 在值元表的字段中检查函数。 如果找到, Lua 调用此函数来执行加法。__add

元表中每个事件的键是一个字符串 事件名称以两个下划线为前缀; 相应的值称为元值。 对于大多数事件,元值必须是一个函数, 然后称为元方法。 在前面的示例中,键是字符串 “” 元方法是执行加法的函数。 除非另有说明, 元方法实际上可以是任何可调用的值, 它要么是一个函数,要么是一个带有元方法的值。__add__call

您可以查询任何值的元表 使用 getmetatable 函数。 Lua 使用原始访问查询元表中的元方法(请参阅 rawget)。

您可以替换表的元表 使用可设置的函数。 您不能从 Lua 代码更改其他类型的元表, 除非使用调试库 (§6.10)。

表和完整的用户数据具有单独的元表, 尽管多个表和用户数据可以共享其元表。 所有其他类型的值共享每个类型的一个元表; 也就是说,所有数字都有一个元表, 一个用于所有字符串等。 默认情况下,值没有元表, 但是字符串库为字符串类型设置了一个元表(参见 §6.4)。

接下来给出了由元表控制的操作的详细列表。 每个事件都由其相应的键标识。 按照惯例,Lua 使用的所有元表键都由 两个下划线后跟小写拉丁字母。

  • __add加法()操作。 如果加法的任何操作数不是数字, Lua 将尝试调用元方法。 它首先检查第一个操作数(即使它是一个数字); 如果该操作数未定义 的元方法 , 然后 Lua 将检查第二个操作数。 如果Lua能找到一个元方法, 它调用元方法,将两个操作数作为参数, 和调用的结果 (调整为一个值) 是操作的结果。 否则,如果未找到元方法, Lua 引发错误。+__add
  • __sub减法()运算。 类似于加法操作的行为。-
  • __mul乘法()运算。 类似于加法操作的行为。*
  • __div除法 () 操作。 类似于加法操作的行为。/
  • __mod模()运算。 类似于加法操作的行为。%
  • __pow幂()运算。 类似于加法操作的行为。^
  • __unm否定(一元)运算。 类似于加法操作的行为。-
  • __idiv地板划分()操作。 类似于加法操作的行为。//
  • __band按位 AND () 操作。 类似于加法运算的行为, 除了Lua会尝试元方法 如果任何操作数既不是整数 也不是可强制转换为整数的浮点数(参见 §3.4.3)。&
  • __bor按位 OR () 操作。 行为类似于按位 AND 运算。|
  • __bxor按位独占 OR(二进制)操作。 行为类似于按位 AND 运算。~
  • __bnot按位 NOT(一元)操作。 行为类似于按位 AND 运算。~
  • __shl按位左移 () 操作。 行为类似于按位 AND 运算。<<
  • __shr按位右移 () 操作。 行为类似于按位 AND 运算。>>
  • __concat串联 () 操作。 类似于加法运算的行为, 除了Lua会尝试元方法 如果任何操作数既不是字符串也不是数字 (始终强制到字符串)。..
  • __len长度 () 操作。 如果对象不是字符串, Lua将尝试其元方法。 如果有元方法, Lua 用对象作为参数调用它, 和调用的结果 (始终调整为一个值) 是操作的结果。 如果没有元方法,但对象是表, 然后 Lua 使用表长度运算(参见 §3.4.7)。 否则,Lua 会引发错误。#
  • __eq相等()运算。 类似于加法运算的行为, 除了Lua只会在以下值时尝试元方法 被比较的是两个表或两个完整的用户数据 而且它们并不是原始平等的。 调用的结果始终转换为布尔值。==
  • __lt小于 () 操作。 类似于加法运算的行为, 除了Lua只会在以下值时尝试元方法 被比较既不是数字也不是两个字符串。 此外,调用的结果始终转换为布尔值。<
  • __le不太相等的 () 操作。 行为类似于小于操作。<=
  • __index: 索引访问操作 。 当不是表或 当 中不存在时。 元值在 的元表中查找。table[key]tablekeytabletable

    此事件的元值可以是函数、表、 或任何具有元值的值。 如果它是一个函数, 它被调用为 和 作为参数, 和调用的结果 (调整为一个值) 是操作的结果。 否则 最终结果是使用 . 这种索引是常规的,而不是原始的, 因此可以触发另一个元值。__indextablekeykey__index

  • __newindex: 索引分配 。 与索引事件一样, 当不是表或 当 中不存在时。 元值在 的元表中查找。table[key] = valuetablekeytabletable

    就像索引一样, 此事件的元值可以是函数、表、 或任何具有元值的值。 如果它是一个函数, 它使用 、 和 作为参数调用。 否则 Lua 在此元值上重复索引赋值 具有相同的键和值。 此作业是常规的,而不是原始的, 因此可以触发另一个元值。__newindextablekeyvalue__newindex

    每当调用元值时, Lua 不执行基元赋值。 如果需要, 元方法本身可以调用 rawset 来执行分配。__newindex

  • __call: 调用操作 。 当 Lua 尝试调用非函数值时,会发生此事件 (即,不是函数)。 元方法在 中查找。 如果存在, 元方法被调用作为其第一个参数, 后跟原始调用 () 的参数。 通话的所有结果 是操作的结果。 这是唯一允许多个结果的元方法。func(args)funcfuncfuncargs

除了前面的列表, 解释器还尊重元表中的以下键:(参见 §2.5.3)、(参见 §3.3.8)、(参见 §2.5.4), 和。 (条目 , 当它包含一个字符串时, 可能由 tostring 和错误消息使用。__gc__close__mode__name__name

对于一元运算符(否定、长度和按位 NOT), 元方法是使用虚拟的第二个操作数计算和调用的, 等于第一个。 这个额外的操作数只是为了简化Lua的内部结构 (通过使这些运算符的行为类似于二进制操作) 并可能在将来的版本中删除。 对于大多数用途,这个额外的操作数是无关紧要的。

因为元表是常规表, 它们可以包含任意字段, 不仅是上面定义的事件名称。 标准库中的一些函数 (例如,托字符串) 将元表中的其他字段用于自己的目的。

最好将所有需要的元方法添加到表中 在将其设置为某个对象的元表之前。 特别是,元方法仅在此顺序下有效 之后(参见 §2.5.3)。 设置对象的元表也是一种很好的做法 在创建之后。__gc

2.5 – 垃圾回收

Lua 执行自动内存管理。 这意味着 您不必担心为新对象分配内存 或者在不再需要对象时释放它。 Lua 通过运行自动管理内存 垃圾回收器,用于收集所有对象。 Lua 使用的所有内存都受到自动管理: 字符串、表、用户数据、函数、线程、内部结构等。

一旦收集器可以确定对象,该对象就被视为已死 在程序的正常执行中不会再次访问。 (这里的“正常执行”不包括终结器, 可以复活死物(见§2.5.3), 并且还排除使用调试库的操作。 注意,收集器可以确定对象的时间 《已死》可能与程序员的期望不符。 唯一的保证是Lua不会收集对象 在程序的正常执行中仍然可以访问, 它最终会收集一个对象 这是无法从Lua访问的。 (在这里,无法从 Lua 访问意味着既不是变量也不是 另一个活动对象引用该对象。 因为Lua对C代码一无所知, 它从不收集可通过注册表访问的对象(参见 §4.3), 其中包括全球环境(见§2.2)。

Lua 中的垃圾回收器 (GC) 可以在两种模式下工作: 增量和代际。

具有默认参数的默认 GC 模式 足以满足大多数用途。 但是,浪费大量时间的程序 分配和释放内存可以从其他设置中受益。 请记住,GC 行为是不可移植的 跨平台和跨不同的 Lua 版本; 因此,最佳设置也是不可移植的。

您可以通过在 C 中调用 lua_gc 来更改 GC 模式和参数 或在卢阿收集垃圾。 您还可以使用这些功能来控制 直接收集器(例如,停止并重新启动它)。

2.5.1 – 增量垃圾回收

在增量模式下, 每个气相色谱循环都以小步骤执行标记和扫描收集 与程序的执行交错。 在这种模式下, 收集器使用三个数字来控制其垃圾收集周期: 垃圾收集者停顿了一下, 垃圾收集器阶跃乘数, 和垃圾收集器步长

垃圾收集器暂停 控制收集器在开始新周期之前等待的时间。 收集器在使用内存时开始新的循环 在上一个集合之后命中 n% 的使用量。 值越大,收集器的攻击性越小。 值等于或小于 100 表示收集器不会等待 开始一个新的周期。 值 200 表示收集器等待正在使用的总内存 在开始新周期之前翻倍。 默认值为 200;最大值为 1000。

垃圾收集器阶跃倍增器 控制收集器相对于 内存分配, 那是 它为每个元素标记或扫描的元素数量 分配的千字节内存。 较大的值使收集器更具侵略性,但也会增加 每个增量步骤的大小。 不应使用小于 100 的值, 因为它们使收集器太慢并且 可能导致收集器永远不会完成一个循环。 默认值为 100;最大值为 1000。

垃圾收集器步长控制 每个增量步骤的大小, 具体说明器分配多少字节 在执行步骤之前。 此参数是对数的: 值 n 表示解释器将在步骤之间分配 2n 个字节,并在步骤期间执行等效工作。 较大的值(例如,60)使收集器停止世界 (非增量)收集器。 默认值为 13, 这意味着步长约为 8 KB。

2.5.2 – 分代垃圾回收

在分代模式下, 收集器经常进行次要收集, 仅遍历最近创建的对象。 如果在次要收集后内存的使用仍高于限制, 收藏家做一个停止世界的主要收藏, 遍历所有对象。 分代模式使用两个参数: 次要乘数主要乘数。

次要乘数控制次要集合的频率。 对于次要乘数 x, 新的次要收集将在内存时完成 增长比上一个主要之后使用的内存大 x% 收集。 例如,对于 20 的乘数, 收集器在使用内存时会做次要收集 比上一个主要集合后的使用量大 20%。 默认值为 20;最大值为 200。

主要乘数控制主要集合的频率。 对于主要乘数 x, 当记忆时将完成新的主要集合 增长比上一个主要之后使用的内存大 x% 收集。 例如,对于乘数 100, 收集器在使用内存时会做一个主要的收集 在上一个集合之后,使用量大于两倍。 默认值为 100;最大值为 1000。

2.5.3 – 垃圾回收元方法

可以为表设置垃圾回收器元方法 并且,使用 C API, 获取完整的用户数据(参见 §2.4)。 这些元方法称为终结器, 当垃圾回收器检测到 相应的表或用户数据已失效。 终结器允许您协调 Lua 的垃圾收集 通过外部资源管理,例如关闭文件, 网络或数据库连接, 或释放自己的记忆。

对于在收集时要最终确定的对象(表或用户数据), 您必须将其标记为最终确定。 在设置对象元表时将对象标记为完成 元表有一个元方法。 请注意,如果设置不带字段的元表 然后稍后在元表中创建该字段, 不会将对象标记为完成。__gc__gc

当标记的对象失效时, 垃圾回收器不会立即收集它。 相反,Lua把它放在一个列表中。 收集后, Lua浏览了一下这个清单。 对于列表中的每个对象, 它检查对象的元方法: 如果存在, Lua 使用对象作为其单个参数调用它。__gc

在每个垃圾收集周期结束时, 终结器被调用 对象被标记为定稿的相反顺序, 在该周期中收集的人中; 也就是说,要调用的第一个终结器是关联的终结器 将对象标记为程序的最后一个。 每个终结器的执行可能发生在以下任何时间点 常规代码的执行。

因为正在收集的对象仍必须由终结器使用, 该对象(以及只能通过它访问的其他对象) 必须被路亚复活。 通常,这种复活是短暂的, 对象内存在下一个垃圾回收周期中释放。 但是,如果终结器将对象存储在某个全局位置 (例如,全局变量), 那么复活是永久的。 此外,如果终结器再次标记要完成的终结对象, 它的终结器将在下一个周期中再次调用,其中 对象已死。 无论如何, 对象内存仅在 GC 循环中释放,其中 对象已失效,未标记为完成。

关闭状态时(请参阅lua_close), Lua 调用标记为完成的所有对象的终结器, 按照标记它们的相反顺序。 如果任何终结器在该阶段标记要收集的对象, 这些标记不起作用。

终结器不能生成也不能运行垃圾回收器。 因为它们可以在不可预测的时间运行, 限制每个终结器是一种很好的做法 达到正确释放所需的最低限度 其关联资源。

运行终结器时的任何错误都会生成警告; 错误不会传播。

2.5.4 – 弱表

弱表是其元素是弱引用。 垃圾回收器将忽略弱引用。 换句话说, 如果对对象的唯一引用是弱引用, 然后垃圾回收器将收集该对象。

弱表可以具有弱键和/或弱值。 具有弱值的表允许收集其值, 但阻止收集其密钥。 同时具有弱键和弱值的表允许收集 键和值。 在任何情况下,如果收集了键或值, 整个对将从表中删除。 表的弱点由其元表的字段控制。 此元值(如果存在)必须是以下字符串之一: “”,用于具有弱键的表; “”,用于具有弱值的表; 或 “”,表示同时具有弱键和值的表。__modekvkv

具有弱键和强值的表 也称为星历表。 在星历表中, 仅当值的键可访问时,该值才被视为可访问。 特别 如果对键的唯一引用来自其值, 该对将被删除。

表弱点的任何更改只能生效 在下一个收集周期。 特别是,如果您将弱点更改为更强的模式, Lua 可能仍会从该表中收集一些物品 在更改生效之前。

仅具有显式构造的对象 从弱表中删除。 值,例如数字和轻 C 函数, 不受垃圾收集, 因此不会从弱表中删除 (除非收集其关联值)。 尽管字符串需要垃圾回收, 它们没有明确的结构和 他们的平等是按价值计算的; 它们的行为更像值而不是对象。 因此,它们不会从弱表中删除。

复活的物体 (即,正在定稿的对象 以及只能通过最终确定的对象访问的对象) 在弱表中具有特殊行为。 在运行终结器之前,将它们从弱值中删除, 但仅在下一个集合中从弱键中删除 运行其终结器后,当此类对象实际释放时。 此行为允许终结器访问属性 通过弱表与对象关联。

如果弱表在集合周期中复活的对象中, 在下一个周期之前,它可能无法正确清除。

2.6 – 协程

Lua 支持协程, 也称为协作多线程。 Lua 中的协程表示独立的执行线程。 但是,与多线程系统中的线程不同, 协程仅通过显式调用来暂停其执行 一个屈服函数。

您可以通过调用 coroutine.create 来创建协程。 它唯一的参数是一个函数 这是协程的主要功能。 该函数仅创建一个新的协程和 返回它的句柄(线程类型的对象); 它不会启动协程。create

通过调用 coroutine.resume 来执行协程。 当您第一次调用 coroutine.resume 时, 作为其第一个参数传递 由 coroutine.create 返回的线程, 协程通过以下方式开始执行 调用其主函数。 传递给协程.resume 的额外参数被传递 作为该函数的参数。 协程开始运行后, 它一直运行到终止或屈服

协程可以通过两种方式终止其执行: 通常,当其主函数返回时 (明示或隐含,在最后一条指令之后); 如果存在未受保护的错误,则异常。 在正常终止的情况下,coroutine.resume 返回 true, 加上协程 Main 函数返回的任何值。 如果出现错误,coroutine.resume 将返回 false 加上错误对象。 在这种情况下,协程不会展开其堆栈, 以便可以在错误后对其进行检查 使用调试 API。

协程通过调用协程产生。 当协程产生时, 相应的协程恢复立即返回, 即使产量发生在嵌套函数调用中 (也就是说,不在主函数中, 但在由主函数直接或间接调用的函数中)。 在 yield 的情况下,coroutine.resume 也返回 true, 加上传递给 coroutine.yield 的任何值。 下次恢复相同的协程时, 它从它屈服的地方继续执行, 调用 coroutine.yield 返回任何额外的 传递给 coroutine.resume 的参数。

coroutine.create一样, coroutine.wrap 函数还创建了一个协程, 但不是返回协程本身, 它返回一个函数,该函数在调用时恢复协程。 传递给此函数的任何参数 作为额外的参数转到 coroutine.resume。coroutine.wrap 返回 coroutine.resume 返回的所有值, 除了第一个(布尔错误代码)。 与coroutine.resume不同, Coroutine.wrap 创建的函数会将任何错误传播给调用方。 在这种情况下, 该函数还会关闭协程(请参见协程)。

作为协程工作原理的示例, 请考虑以下代码:

     function foo (a)
       print("foo", a)
       return coroutine.yield(2*a)
     end
     
     co = coroutine.create(function (a,b)
           print("co-body", a, b)
           local r = foo(a+1)
           print("co-body", r)
           local r, s = coroutine.yield(a+b, a-b)
           print("co-body", r, s)
           return b, "end"
     end)
     
     print("main", coroutine.resume(co, 1, 10))
     print("main", coroutine.resume(co, "r"))
     print("main", coroutine.resume(co, "x", "y"))
     print("main", coroutine.resume(co, "x", "y"))

运行它时,它会生成以下输出:

     co-body 1       10
     foo     2
     main    true    4
     co-body r
     main    true    11      -9
     co-body x       y
     main    true    10      end
     main    false   cannot resume dead coroutine

您还可以通过 C API 创建和操作协程: 请参阅函数lua_newthread、lua_resume、 和lua_yield。

3 – 语言

本节介绍 Lua 的词法、语法和语义。 换句话说, 本节介绍 哪些令牌有效, 它们如何组合, 以及它们的组合意味着什么。

语言结构将使用通常的扩展 BNF 表示法进行解释, 其中 {a} 表示 0 个或多个 a,并且 [a] 表示可选的 a。 非终端显示为非终端, 关键字显示为kword, 其他终端符号显示为“=”。 Lua 的完整语法可以在本手册末尾的 §9 中找到。

3.1 – 词汇约定

Lua 是一种自由格式的语言。 它忽略词汇元素(标记)之间的空格和注释, 两个令牌之间的分隔符除外。 在源代码中, Lua 将标准 ASCII 空格识别为空格 字符空间、表单馈送、换行符、 回车符、水平制表符和垂直制表符。

名称(也称为标识符) 在Lua中可以是任何拉丁字母串, 阿拉伯印度数字和下划线, 不以数字开头,并且 不是一个保留的词。 标识符用于命名变量、表字段和标签。

保留以下关键字 并且不能用作名称:

     and       break     do        else      elseif    end
     false     for       function  goto      if        in
     local     nil       not       or        repeat    return
     then      true      until     while

Lua 是一种区分大小写的语言:是一个保留字,但 和 是两个不同的有效名称。 作为惯例, 程序应避免创建 以下划线开头的名称,后跟 一个或多个大写字母(如 _VERSION)。andAndAND

以下字符串表示其他标记:

     +     -     *     /     %     ^     #
     &     ~     |     <<    >>    //
     ==    ~=    <=    >=    <     >     =
     (     )     {     }     [     ]     ::
     ;     :     ,     .     ..    ...

短文本字符串可以通过匹配的单引号或双引号分隔, 并且可以包含以下类似 C 的转义序列: ''(铃铛), ''(退格), “”(表单提要), ''(换行符), ''(回车), ''(水平制表符), ''(垂直制表符), ''(反斜杠), ''(引号 [双引号]), 和“”(撇号 [单引号])。 反斜杠后跟换行符 在字符串中生成换行符。 转义序列 '' 跳过以下跨度 的空格字符, 包括换行符; 断开和缩进长文本字符串特别有用 分成多行,不添加换行符和空格 放入字符串内容中。 短文本字符串不能包含未转义的换行符 也不是未形成有效转义序列的转义。\a\b\f\n\r\t\v\\\"\'\z

我们可以在短文本字符串中指定任何字节, 包括嵌入的零, 按其数值。 这是可以做到的 随着转义序列, 其中 XX 是正好两个十六进制数字的序列, 或带有转义序列, 其中 ddd 是最多三个十进制数字的序列。 (请注意,如果十进制转义序列后跟数字, 它必须正好用三位数字表示。\xXX\ddd

Unicode 字符的 UTF-8 编码 可以插入到文字字符串中 转义序列(带强制括大括号), 其中 XXX 是一个或多个十六进制数字的序列 表示字符代码点。 此代码点可以是小于 231 的任何值。 (Lua 在这里使用原始的 UTF-8 规范, 这不限于有效的 Unicode 代码点。\u{XXX}

文字字符串也可以使用长格式定义 用长括号括起来。 我们将级别 n 的开口长括号定义为开口 方括号后跟 n 个等号,后跟另一个等号 左方括号。 因此,级别 0 的左长括号写为 , 级别 1 的左长括号写为 , 等等。 右长括号的定义类似; 例如 级别 4 的右长括号写为 。 长文字以任何级别的开始长括号开头,并且 在相同级别的第一个结束长括号处结束。 它可以包含除同一级别的右括号之外的任何文本。 这种括号形式的文字可以运行几行, 不要解释任何转义序列, 并忽略任何其他级别的长括号。 任何类型的行尾序列 (回车符、换行符、回车符后跟换行符、 或换行符,后跟回车符) 转换为简单的换行符。 当左长括号紧跟换行符时, 字符串中不包含换行符。[[[=[]====]

例如,在使用 ASCII 的系统中 (其中“”编码为 97, 换行符编码为 10,'' 编码为 49), 下面的五个文本字符串表示相同的字符串:a1

     a = 'alo\n123"'
     a = "alo\n123\""
     a = '\97lo\10\04923"'
     a = [[alo
     123"]]
     a = [==[
     alo
     123"]==]

文本字符串中的任何字节不是 明确受先前规则影响表示自身。 但是,Lua 在文本模式下打开文件进行解析, 并且系统的文件功能可能存在以下问题 一些控制字符。 所以,代表更安全 二进制数据作为引用的文字 非文本字符的显式转义序列。

数字常量(或数字) 可以用可选的小数部分编写 和可选的小数指数, 用字母“”或“”标记。 Lua 也接受十六进制常量, 以 或 开头。 十六进制常量也接受可选的小数部分 加上一个可选的二进制指数, 用字母“”或“”标记,并以十进制书写。 (例如,表示 1984, 即 0x1f / 16 乘以 210eE0x0XpP0x1.fp10

带有基数点或指数的数字常量 表示浮点数; 否则 如果其值适合整数或是十六进制常量, 它表示一个整数; 否则(即溢出的十进制整数数字), 它表示浮点数。 既没有基数点也没有指数的十六进制数字 始终表示整数值; 如果值溢出,它将环绕以适合有效的整数。

有效整数常量的示例包括

     3   345   0xff   0xBEBADA

有效浮点常量的示例包括

     3.0     3.1416     314.16e-2     0.31416E1     34e1
     0x0.1E  0xA23p-4   0X1.921FB54442D18P+1

注释以双连字符 () 开头 字符串之外的任何位置。 如果紧随其后的文本不是左长括号, 评论是一个简短的评论, 一直运行到行的末尾。 否则,这是一个很长的评论, 一直运行到相应的右长括号。----

3.2 – 变量

变量是存储值的地方。 Lua 中有三种变量: 全局变量、局部变量和表字段。

单个名称可以表示全局变量或局部变量 (或函数的形式参数, 这是一种特殊的局部变量):

	var ::= Name

名称表示标识符(参见 §3.1)。

除非明确声明,否则任何变量名都假定为全局变量 作为本地(参见 §3.3.7)。 局部变量在词法上作用域: 局部变量可由函数自由访问 在其范围内定义(参见 §3.5)。

在第一次赋值变量之前,其值为 nil

方括号用于为表编制索引:

	var ::= prefixexp ‘[’ exp ‘]

可以通过元表更改访问表字段的含义 (见§2.4)。

语法只是语法糖:var.Namevar["Name"]

	var ::= prefixexp ‘.’ Name

对全局变量的访问等效于 。 由于块的编译方式, 变量本身从来都不是全局的(参见 §2.2)。x_ENV.x_ENV

3.3 – 声明

Lua 支持一组几乎传统的语句, 与其他常规语言相似。 此套装包括 块、赋值、控制结构、函数调用、 和变量声明。

3.3.1 – 块

块是语句列表, 按顺序执行:

	block ::= {stat}

Lua 有语句,允许您用分号分隔语句, 用分号开始块 或者按顺序写两个分号:

	stat ::= ‘;

函数调用和赋值 可以以左括号开头。 这种可能性导致Lua的语法含糊不清。 请考虑以下片段:

     a = b + c
     (print or io.write)('done')

语法可以通过两种方式查看此片段:

     a = b + c(print or io.write)('done')
     
     a = b + c; (print or io.write)('done')

当前解析器总是看到这样的结构 在第一种方式中, 解释左括号 作为调用参数的开头。 为了避免这种歧义, 最好始终在分号前面 以括号开头的语句:

     ;(print or io.write)('done')

可以显式分隔块以生成单个语句:

	stat ::= do block end

显式块很有用 以控制变量声明的范围。 显式块有时也用于 在中间添加返回语句 另一个块(参见 §3.3.4)。

3.3.2 – 块

Lua的编译单位称为。 语法 块只是一个块:

	chunk ::= block

Lua 将块作为匿名函数的主体进行处理 具有可变数量的参数 (参见 §3.4.11)。 因此,块可以定义局部变量, 接收参数并返回值。 此外,这种匿名函数的编译方式如下 称为(参见 §2.2)的外部局部变量的作用域。 生成的函数始终具有唯一的外部变量, 即使它不使用该变量。_ENV_ENV

块可以存储在文件或主机程序内的字符串中。 要执行一个块, Lua首先加载它, 将块的代码预编译为虚拟机的指令, 然后 Lua 执行编译后的代码 使用虚拟机的解释器。

块也可以预编译为二进制形式; 有关详细信息,请参阅程序和函数 string.dump。 源代码和编译形式的程序是可以互换的; Lua 会自动检测文件类型并采取相应措施(请参阅加载)。luac

3.3.3 – 分配

Lua 允许多个分配。 因此,赋值的语法 在左侧定义变量列表 以及右侧的表达式列表。 两个列表中的元素都用逗号分隔:

	stat ::= varlist ‘=’ explist
	varlist ::= var {‘,’ var}
	explist ::= exp {‘,’ exp}

表达式在 §3.4 中讨论。

在作业之前, 值列表调整为 变量列表(参见 §3.4.12)。

如果变量既赋值又读取 在多重作业中, Lua 确保所有读取都获取变量的值 在作业之前。 因此代码

     i = 3
     i, a[i] = i+1, 20

设置为 20,而不影响,因为计算了 in(到 3) 在分配之前 4. 同样,该行a[3]a[4]ia[i]

     x, y = y, x

交换 和 的值 , 和xy

     x, y, z = y, z, x

循环排列 、 和 的值。xyz

请注意,此保证仅涵盖访问 语法在赋值语句内。 如果在赋值期间调用的函数或元方法 更改变量的值, Lua 不保证该访问的顺序。

对全局名称的赋值等效于赋值(参见 §2.2)。x = val_ENV.x = val

表字段赋值的含义和 全局变量(实际上也是表字段) 可以通过元表进行更改(参见 §2.4)。

3.3.4 – 控制结构

控制结构 ifwhile 和 repeat具有通常的含义和 熟悉的语法:

	stat ::= while exp do block end
	stat ::= repeat block until exp
	stat ::= if exp then block {elseif exp then block} [else block] end

Lua 还有一个 for 语句,有两种风格(参见 §3.3.5)。

的条件表达式 控件结构可以返回任何值。 假和测试都是的。 所有值都不同于 nil 和 false 检验 true。 特别是,数字 0 和空字符串也测试 true。

重复-直到循环中, 内部块不以 till 关键字结尾, 但只有在条件之后。 因此,条件可以引用局部变量 在循环块内声明。

goto 语句将程序控件转移到标签。 出于语法原因, Lua 中的标签也被视为语句:

	stat ::= goto Name
	stat ::= label
	label ::= ‘::’ Name ‘::

标签在定义它的整个块中可见, 嵌套函数内部除外。 goto 可以跳转到任何可见标签,只要它不 进入局部变量的范围。 不应声明标签 其中,具有相同名称的标签可见, 即使此其他标签已在封闭块中声明。

break 语句终止 whilerepeat或 for 循环的执行, 跳到循环后的下一条语句:

	stat ::= break

中断结束最里面的封闭循环。

return 语句用于返回值 从函数或块 (作为匿名函数处理)。 函数可以返回多个值, 所以 return 语句的语法是

	stat ::= return [explist] [‘;’]

返回语句只能写 作为块的最后一个语句。 如果需要在块中间返回, 然后可以使用显式内部块, 如成语, 因为现在返回是其(内部)块中的最后一个语句。do return end

3.3.5 – 对于语句

for 语句有两种形式: 一个数字和一个通用。

数字 for 循环

数字 for 循环重复一个代码块,而 控制变量经历算术级数。 它具有以下语法:

	stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end

给定的标识符(名称)定义控制变量, 这是循环体()局部的新变量。

循环首先计算一次三个控制表达式。 它们的值分别称为 初始值限制步长。 如果该步骤不存在,则默认为 1。

如果初始值和步长都是整数, 循环是用整数完成的; 请注意,限制可能不是整数。 否则,这三个值将转换为 浮点,循环是用浮点完成的。 在这种情况下,请注意浮点精度。

初始化后, 循环体与控制变量的值重复 经历算术级数, 从初始值开始, 具有步骤给出的共同差异。 负步长使序列递减; 等于零的步骤会引发错误。 当值小于时,循环继续 或等于限制 (大于或等于负步长)。 如果初始值已经大于限制 (或小于,如果步长为负), 正文不执行。

对于整数循环, 控制变量从不环绕; 相反,循环在溢出的情况下结束。

不应更改控制变量的值 在循环期间。 如果你在循环后需要它的值, 在退出循环之前将其分配给另一个变量。

泛型 for 循环

泛型 for 语句适用于函数, 称为迭代器。 在每次迭代中,调用迭代器函数以生成一个新值, 当此新值为 nil 时停止。 泛型 for 循环具有以下语法:

	stat ::= for namelist in explist do block end
	namelist ::= Name {‘,’ Name}

表示语句,例如

     for var_1, ···, var_n in explist do body end

工作原理如下。

这些名称var_i声明循环体的局部循环变量。 这些变量中的第一个是控制变量

循环首先计算 explist 以生成四个值: 迭代器函数, 一个状态, 控制变量的初始值, 和收盘价

然后,在每次迭代中, Lua 使用两个参数调用迭代器函数: 状态和控制变量。 然后将此调用的结果分配给循环变量, 遵循多重分配的规则(参见 §3.3.3)。 如果控制变量变为 nil, 循环终止。 否则,主体被执行并且循环 到下一个迭代。

收盘价的行为类似于 待闭变量(参见 §3.3.8), 可用于在循环结束时释放资源。 否则,它不会干扰循环。

不应更改控制变量的值 在循环期间。

3.3.6 – 作为语句调用的函数

为了允许可能的副作用, 函数调用可以作为语句执行:

	stat ::= functioncall

在这种情况下,所有返回的值都将被丢弃。 函数调用在 §3.4.10 中进行了说明。

3.3.7 – 本地声明

局部变量可以在块内的任何位置声明。 声明可以包含初始化:

	stat ::= local attnamelist [‘=’ explist]
	attnamelist ::=  Name attrib {‘,’ Name attrib}

如果存在,则初始赋值具有相同的语义 多重转让(参见 §3.3.3)。 否则,所有变量都使用 nil 初始化。

每个变量名称都可以由一个属性作为后缀 (尖括号之间的名称):

	attrib ::= [‘<’ Name ‘>’]

有两种可能的属性:,它声明一个常量变量, 即不能分配给的变量 初始化后; 和 ,它声明一个要闭合的变量(参见 §3.3.8)。 变量列表最多可以包含一个要关闭的变量。constclose

块也是一个块(参见 §3.3.2), 因此,局部变量可以在任何显式块之外的块中声明。

局部变量的可见性规则在 §3.5 中进行了解释。

3.3.8 – 待闭合变量

待闭变量的行为类似于常量局部变量, 除了每当变量时其值关闭 超出范围,包括正常的块终止, 通过中断/转到/返回退出其块, 或因错误而退出。

在这里,关闭一个值意味着 以调用其元方法。 调用元方法时, 值本身作为第一个参数传递 以及导致退出的错误对象(如果有) 作为第二个参数传递; 如果没有错误,则第二个参数为 nil__close

分配给要闭合变量的值 必须有一个元方法 或为假值。 (nil 和 false 作为要关闭的值被忽略。__close

如果多个待闭合变量在同一事件中超出范围, 它们以与声明的顺序相反的方式关闭。

如果在运行关闭方法时出现任何错误, 该错误像常规代码中的错误一样处理 定义变量的位置。 错误后, 仍将调用其他挂起的关闭方法。

如果协程生成并且再也不会恢复, 有些变量可能永远不会超出范围, 因此,它们永远不会关闭。 (这些变量是在协程中创建的变量 并在协程产生点的范围内。 同样,如果协程以错误结尾, 它不会展开它的堆栈, 所以它不会关闭任何变量。 在这两种情况下, 您可以使用终结器 或调用 coroutine.close 关闭变量。 但是,如果创建了协程 通过coroutine.wrap, 然后它对应的函数将关闭协程 万一出现错误。

3.4 – 表达式

Lua 中的基本表达式如下:

	exp ::= prefixexp
	exp ::= nil | false | true
	exp ::= Numeral
	exp ::= LiteralString
	exp ::= functiondef
	exp ::= tableconstructor
	exp ::= ‘...’
	exp ::= exp binop exp
	exp ::= unop exp
	prefixexp ::= var | functioncall | ‘(’ exp ‘)

数字和文字字符串在 §3.1 中解释; 变量在 §3.2 中解释; 函数定义在 §3.4.11 中解释; 函数调用在 §3.4.10 中进行了说明; 表构造函数在 §3.4.9 中进行了说明。 瓦拉格表达式, 用三个点 ('') 表示,只能在以下情况下使用 直接在可变参数函数内; 它们在 §3.4.11 中有解释。...

二元运算符包括算术运算符(参见 §3.4.1), 按位运算符(参见 §3.4.2), 关系运算符(参见 §3.4.4)、逻辑运算符(参见 §3.4.5)、 和串联运算符(参见 §3.4.6)。 一元运算符包括一元减号(参见 §3.4.1), 一元位 NOT(参见 §3.4.2), 一元逻辑不是(见§3.4.5), 和一元长度运算符(参见 §3.4.7)。

3.4.1 – 算术运算符

Lua 支持以下算术运算符:

  • +: 加法
  • -减法
  • *: 乘法
  • /: 浮点分割
  • 地板划分
  • %: 模数
  • ^: 
  • -: 一元减号

除了幂和浮点除法, 算术运算符的工作方式如下: 如果两个操作数都是整数, 该操作对整数执行,结果为整数。 否则,如果两个操作数都是数字, 然后它们被转换为浮点数, 操作按照计算机的规则执行 用于浮点运算 (通常是IEEE 754标准), 结果是浮点数。 (字符串库将字符串强制转换为数字 算术运算;有关详细信息,请参见 §3.4.3。

幂和浮点除法 () 始终将其操作数转换为浮点数 结果总是浮点数。 幂使用ISO C函数, 这样它也适用于非整数指数。/pow

楼层划分()是一个分区 将商四舍五入到负无穷大, 导致其操作数划分的底线。//

模定义为除法的余数 将商四舍五入到负无穷大(地板除法)。

在整数算术中溢出的情况下, 所有操作都围绕着。

3.4.2 – 按位运算符

Lua 支持以下按位运算符:

  • &按位和
  • |按位或
  • ~按位独占 OR
  • >>右移
  • <<左移
  • ~一元位 NOT

所有按位运算将其操作数转换为整数 (见§3.4.3), 对这些整数的所有位进行操作, 并生成一个整数。

左右移位都用零填充空位。 负位移向另一个方向; 绝对值等于或高于的位移 整数中的位数 结果为零(因为所有位都移出)。

3.4.3 – 胁迫和转换

Lua提供了一些自动转换 运行时的类型和表示形式。 按位运算符始终将浮点操作数转换为整数。 幂和浮点除法 始终将整数操作数转换为浮点数。 应用于混合数的所有其他算术运算 (整数和浮点数)将整数操作数转换为浮点数。 C API 还将两个整数转换为浮点数和 根据需要浮点为整数。 此外,字符串连接接受数字作为参数, 除了字符串。

在从整数到浮点数的转换中, 如果整数值精确表示为浮点数, 这就是结果。 否则 转换获得最接近的更高或 最接近的较低可表示值。 这种转换永远不会失败。

从浮点型到整数的转换 检查浮点数是否具有整数的精确表示形式 (即浮点数具有整数值和 它在整数表示的范围内)。 如果是这样,则表示就是结果。 否则,转换将失败。

Lua的几个地方在必要时将字符串强制为数字。 特别 字符串库设置尝试强制的元方法 所有算术运算中的字符串到数字。 如果转换失败, 库调用另一个操作数的元方法 (如果存在)或引发错误。 请注意,按位运算符不执行此强制操作。

不依赖 从字符串到数字的隐式强制, 因为它们并不总是适用; 特别是,为假并引发错误 (参见 §3.4.4)。 这些强制存在主要是为了兼容性,可以消除 在语言的未来版本中。"1"==1"1"<1

字符串转换为整数或浮点数 遵循其语法和Lua词法分析器的规则。 字符串还可以具有前导和尾随空格和符号。 从字符串到数字的所有转换 接受点和当前区域设置标记 作为基数字符。 (然而,Lua词法分析器只接受一个点。 如果字符串不是有效的数字, 转换失败。 如有必要,将转换第一步的结果 按照前面的规则转换为特定数字子类型 用于浮点数和整数之间的转换。

从数字到字符串的转换使用 非指定的人类可读格式。 要以任何特定方式将数字转换为字符串, 使用函数 string.format。

3.4.4 – 关系运算符

Lua 支持以下关系运算符:

  • ==: 相等
  • ~=: 不等式
  • <小于
  • >大于
  • <=小于或等于
  • >=大于或等于

这些运算符总是导致 false 或 true

相等 () 首先比较其操作数的类型。 如果类型不同,则结果为 false。 否则,将比较操作数的值。 如果字符串具有相同的字节内容,则字符串相等。 如果数字表示相同的数学值,则它们相等。==

表、用户数据和线程 通过参考比较: 仅当两个对象是同一对象时,它们才被视为相等。 每次创建新对象时 (表、用户数据或线程), 此新对象不同于以前存在的任何对象。 函数总是等于它自己。 具有任何可检测差异的功能 (不同的行为,不同的定义)总是不同的。 在不同时间创建但无法检测到差异的函数 可以归类为相等或不相等 (取决于内部缓存详细信息)。

您可以更改 Lua 比较表和用户数据的方式 通过使用元方法(参见 §2.4)。__eq

相等比较不会将字符串转换为数字 反之亦然。 因此,计算结果为, 和 和 表示不同 表中的条目。"0"==0t[0]t["0"]

运算符正好是相等式的否定 ()。~===

订单运算符的工作方式如下。 如果两个参数都是数字, 然后根据它们的数学值进行比较, 无论其亚型如何。 否则,如果两个参数都是字符串, 然后根据当前区域设置比较它们的值。 否则,Lua 会尝试调用 or 元方法(参见 §2.4)。 比较将转换为 和 转换为 。__lt__lea > bb < aa >= bb <= a

遵循 IEEE 754 标准, 特殊值 NaN 被认为不小于, 既不等于,也不大于任何价值,包括其自身。

3.4.5 – 逻辑运算符

Lua 中的逻辑运算符是 andor 和 not。 与控制结构(参见 §3.3.4)一样, 所有逻辑运算符都认为 false 和 nil 都为假 以及其他任何真实的东西。

否定运算符并不总是返回 false 或 true。 连接运算符返回其第一个参数 如果此值为; 否则,返回其第二个参数。 析取运算符返回其第一个参数 如果此值不同于 nil 和 false; 否则,返回其第二个参数。 /或使用短路评估; 那是 仅在必要时计算第二个操作数。 以下是一些示例:

     10 or 20            --> 10
     10 or error()       --> 10
     nil or "a"          --> "a"
     nil and 10          --> nil
     false and error()   --> false
     false and nil       --> false
     false or nil        --> nil
     10 and 20           --> 20

3.4.6 – 串联

Lua 中的字符串连接运算符是 用两个点 ('') 表示。 如果两个操作数都是字符串或数字, 然后将数字转换为字符串 采用非指定格式(参见 §3.4.3)。 否则,将调用元方法(参见 §2.4)。..__concat

3.4.7 – 长度运算符

长度运算符由一元前缀运算符表示。#

字符串的长度是其字节数。 (这是字符串长度的通常含义,当每个 字符为一个字节。

应用于表的长度运算符 返回该表中的边框。 表中的边框是任何非负整数 满足以下条件:t

     (border == 0 or t[border] ~= nil) and
     (t[border + 1] == nil or border == math.maxinteger)

用言语来说, 边框是表中存在的任何正整数索引 后跟一个缺失的索引, 加上两个限制情况: 零,当索引 1 不存在时; 以及整数的最大值(如果存在该索引)。 请注意,不是正整数的键 不要干扰边界。

只有一个边框的表称为序列。 例如,表是一个序列, 因为它只有一个边框 (5)。 表格有两个边框(3 和 5), 因此它不是一个序列。 (索引 4 处的 nil 称为。 该表有三个边框(0、3 和 6), 所以它也不是一个序列。 该表是边框为 0 的序列。{10, 20, 30, 40, 50}{10, 20, 30, nil, 50}{nil, 20, 30, nil, nil, 60, nil}{}

当 是序列时,返回其唯一的边框, 这与序列长度的直观概念相对应。 当不是序列时,可以返回其任何边界。 (确切的取决于细节 表的内部表示, 这反过来又取决于表的填充方式和 其非数字键的内存地址。t#tt#t

表长度的计算 保证最差时间为 O(log n), 其中 n 是表中最大的整数键。

程序可以修改长度运算符的行为 通过元方法的任何值,但字符串除外(参见 §2.4)。__len

3.4.8 – 优先级

Lua 中的运算符优先级如下表所示, 从低优先级到高优先级:

     or
     and
     <     >     <=    >=    ~=    ==
     |
     ~
     &
     <<    >>
     ..
     +     -
     *     /     //    %
     unary operators (not   #     -     ~)
     ^

照常 可以使用括号更改表达式的优先级。 串联 (“”) 和幂 (”) 运算符是右关联。 所有其他二元运算符都保留关联。..^

3.4.9 – 表构造函数

表构造函数是创建表的表达式。 每次计算构造函数时,都会创建一个新表。 构造函数可用于创建空表 或者创建一个表并初始化其某些字段。 构造函数的一般语法是

	tableconstructor ::= ‘{’ [fieldlist] ‘}’
	fieldlist ::= field {fieldsep field} [fieldsep]
	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
	fieldsep ::= ‘,’ | ‘;

表单的每个字段都会向新表添加一个条目 带有键和值。 表单的字段等效于 。 形式的字段等效于 ,其中是连续整数 从 1 开始; 其他格式的字段不会影响此计数。 例如[exp1] = exp2exp1exp2name = exp["name"] = expexp[i] = expi

     a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

相当于

     do
       local t = {}
       t[f(1)] = g
       t[1] = "x"         -- 1st exp
       t[2] = "y"         -- 2nd exp
       t.x = 1            -- t["x"] = 1
       t[3] = f(x)        -- 3rd exp
       t[30] = 23
       t[4] = 45          -- 4th exp
       a = t
     end

构造函数中赋值的顺序未定义。 (仅当存在重复键时,此顺序才相关。

如果列表中的最后一个字段具有表单,并且表达式是多分辨率表达式, 然后此表达式返回的所有值连续进入列表 (参见 §3.4.12)。exp

字段列表可以有一个可选的尾随分隔符, 为了方便机器生成的代码。

3.4.10 – 函数调用

Lua 中的函数调用具有以下语法:

	functioncall ::= prefixexp args

在函数调用中, 评估第一个前缀 EXP 和参数。 如果前缀exp的值具有类型函数, 那么这个函数被调用 与给定的参数。 否则,如果存在, 前缀 EXP 元方法称为: 它的第一个参数是前缀 ExExp 的值, 后跟原始调用参数 (见§2.4)。__call

表格

	functioncall ::= prefixexp ‘:’ Name args

可用于模拟方法。 调用是 的句法糖, 除非只评估一次。v:name(args)v.name(v,args)v

参数具有以下语法:

	args ::= ‘(’ [explist] ‘)’
	args ::= tableconstructor
	args ::= LiteralString

在调用之前计算所有参数表达式。 表单的调用是 句法糖 ; 也就是说,参数列表是单个新表。 表单(或或)的调用 是句法糖; 也就是说,参数列表是单个文本字符串。f{fields}f({fields})f'string'f"string"f[[string]]f('string')

不在 待闭合变量的作用域称为尾部调用。 Lua 实现了正确的尾部调用(或适当的尾部递归): 在尾声中, 被调用的函数重用调用函数的堆栈条目。 因此,嵌套尾部调用的数量没有限制 程序可以执行。 但是,尾部调用会擦除有关 调用函数。 请注意,尾部调用仅发生在特定语法下, 其中返回有一个函数调用作为参数, 并且它超出了任何要关闭的变量的范围。 此语法使调用函数完全返回 被调用函数的返回, 没有任何干预行动。 因此,以下示例都不是尾调用:return functioncall

     return (f(x))        -- results adjusted to 1
     return 2 * f(x)      -- result multiplied by 2
     return x, f(x)       -- additional results
     f(x); return         -- results discarded
     return x or f(x)     -- results adjusted to 1

3.4.11 – 函数定义

函数定义的语法是

	functiondef ::= function funcbody
	funcbody ::= ‘(’ [parlist] ‘)’ block end

以下语法糖简化了函数定义:

	stat ::= function funcname funcbody
	stat ::= local function Name funcbody
	funcname ::= Name {‘.’ Name} [‘:’ Name]

声明

     function f () body end

翻译为

     f = function () body end

声明

     function t.a.b.c.f () body end

翻译为

     t.a.b.c.f = function () body end

声明

     local function f () body end

翻译为

     local f; f = function () body end

不要

     local f = function () body end

(这仅在函数的主体时有所不同 包含对 的引用。)f

函数定义是一个可执行的表达式, 其值具有类型函数。 当 Lua 预编译一个块时, 它的所有函数体也是预编译的, 但它们尚未创建。 然后,每当 Lua 执行函数定义时, 函数实例(或关闭)。 此函数实例或闭包, 是表达式的最终值。

参数充当局部变量,即 使用参数值初始化:

	parlist ::= namelist [‘,’ ‘...’] | ‘...

调用 Lua 函数时, 它将其参数列表调整为 其参数列表的长度(参见 §3.4.12), 除非函数是可变参数函数, 由三个点 ('') 表示 在其参数列表的末尾。 可变参数函数不调整其参数列表; 相反,它收集所有额外的参数并提供它们 通过 vararg 表达式到函数, 也写成三个点。 此表达式的值是所有实际额外参数的列表, 类似于具有多个结果的函数(参见 §3.4.12)。...

例如,请考虑以下定义:

     function f(a, b) end
     function g(a, b, ...) end
     function r() return 1,2,3 end

然后,我们有以下从参数到参数的映射和 对于 vararg 表达式:

     CALL             PARAMETERS
     
     f(3)             a=3, b=nil
     f(3, 4)          a=3, b=4
     f(3, 4, 5)       a=3, b=4
     f(r(), 10)       a=1, b=10
     f(r())           a=1, b=2
     
     g(3)             a=3, b=nil, ... -->  (nothing)
     g(3, 4)          a=3, b=4,   ... -->  (nothing)
     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
     g(5, r())        a=5, b=1,   ... -->  2  3

结果使用 return 语句返回(参见 §3.3.4)。 如果控件到达函数的末尾 没有遇到返回语句, 然后函数返回没有结果。

值的数量存在系统相关限制 函数可能会返回。 此限制保证大于 1000。

冒号语法 用于模拟方法, 向函数添加一个隐式额外参数。 因此,声明self

     function t.a.b.c:f (params) body end

是句法糖

     t.a.b.c.f = function (self, params) body end

3.4.12 – 表达式列表、多个结果、 和调整

函数调用和 vararg 表达式都可以生成多个值。 这些表达式称为多重表达式

当多重表达式用作最后一个元素时 表达式列表, 表达式的所有结果都将添加到 表达式列表生成的值列表。 请注意,单个表达式 在需要表达式列表的地方 是该(单例)列表中的最后一个表达式。

这些是 Lua 需要表达式列表的地方:

  • 返回语句, 例如(参见§3.3.4)。return e1, e2, e3
  • 表构造函数, 例如(参见§3.4.9)。{e1, e2, e3}
  • 函数调用的参数, 例如(参见§3.4.10)。foo(e1, e2, e3)
  • 多重分配, 例如(参见 §3.3.3)。a , b, c = e1, e2, e3
  • 当地声明, 例如(参见§3.3.7)。local a , b, c = e1, e2, e3
  • 泛型 for 循环中的初始值, 例如(参见 §3.3.5)。for k in e1, e2, e3 do ... end

在最后四个案例中, 表达式列表中的值列表 必须调整到特定长度: 调用非可变参数函数时的参数数 (见 §3.4.11), 多重赋值中的变量数或 当地声明, 以及泛型 for 循环的正好四个值。 调整遵循以下规则: 如果值多于所需值, 多余的值被扔掉; 如果值少于所需值, 该列表使用扩展。 当表达式列表以多锐表达式结尾时, 该表达式的所有结果都输入值列表 调整前。

使用多重表达式时 在表达式列表中,而不是最后一个元素, 或在语法需要单个表达式的地方, Lua 将该表达式的结果列表调整为一个元素。 作为一个特例, 语法需要括号表达式中的单个表达式; 因此,在多重表达式周围添加括号 迫使它只产生一个结果。

我们很少需要在某个地方使用 vararg 表达式 语法需要单个表达式的地方。 (通常之前添加常规参数更简单 可变参数部分并使用该参数。 当有这样的需要时, 我们建议分配 vararg 表达式 到单个变量并使用该变量 取而代之。

下面是一些使用多个表达式的示例。 在所有情况下,当施工需要时 “第 n 个结果”,没有这样的结果, 它使用

     print(x, f())      -- prints x and all results from f().
     print(x, (f()))    -- prints x and the first result from f().
     print(f(), x)      -- prints the first result from f() and x.
     print(1 + f())     -- prints 1 added to the first result from f().
     local x = ...      -- x gets the first vararg argument.
     x,y = ...          -- x gets the first vararg argument,
                        -- y gets the second vararg argument.
     x,y,z = w, f()     -- x gets w, y gets the first result from f(),
                        -- z gets the second result from f().
     x,y,z = f()        -- x gets the first result from f(),
                        -- y gets the second result from f(),
                        -- z gets the third result from f().
     x,y,z = f(), g()   -- x gets the first result from f(),
                        -- y gets the first result from g(),
                        -- z gets the second result from g().
     x,y,z = (f())      -- x gets the first result from f(), y and z get nil.
     return f()         -- returns all results from f().
     return x, ...      -- returns x and all received vararg arguments.
     return x,y,f()     -- returns x, y, and all results from f().
     {f()}              -- creates a list with all results from f().
     {...}              -- creates a list with all vararg arguments.
     {f(), 5}           -- creates a list with the first result from f() and 5.

3.5 – 可见性规则

Lua是一种词汇范围的语言。 局部变量的作用域从后面的第一条语句开始 其声明并持续到最后一个非无效声明 包含声明的最内层块。 (void 语句是标签和空语句。 请考虑以下示例:

     x = 10                -- global variable
     do                    -- new block
       local x = x         -- new 'x', with value 10
       print(x)            --> 10
       x = x+1
       do                  -- another block
         local x = x+1     -- another 'x'
         print(x)          --> 12
       end
       print(x)            --> 11
     end
     print(x)              --> 10  (the global one)

请注意,在类似 的声明中, 新申报的尚未在范围内, 所以第二个指的是外部变量。local x = xxx

由于词法范围规则, 局部变量可由函数自由访问 在其范围内定义。 内部函数使用的局部变量称为upvalue(或外部局部变量,或简称为外部变量) 内部函数内部。

请注意,每次执行本地语句 定义新的局部变量。 请考虑以下示例:

     a = {}
     local x = 20
     for i = 1, 10 do
       local y = 0
       a[i] = function () y = y + 1; return x + y end
     end

循环创建十个闭包 (即匿名函数的十个实例)。 这些闭包中的每一个都使用不同的变量, 而它们都共享相同的.yx

4 – 应用程序接口

本节介绍适用于 Lua 的 C API,即 主机程序可用于通信的 C 函数集 与路亚。 所有 API 函数以及相关类型和常量 在头文件 lua.h 中声明。

即使我们使用术语“功能”, API 中的任何工具都可以作为宏提供。 除非另有说明, 所有这些宏只使用一次它们的每个参数 (除了第一个参数,它始终是 Lua 状态), 因此不会产生任何隐藏的副作用。

与大多数 C 库一样, Lua API 函数不检查其参数 的有效性或一致性。 但是,您可以通过编译 Lua 来更改此行为 定义了宏LUA_USE_APICHECK

Lua 库是完全可重入的: 它没有全局变量。 它将所需的所有信息保存在动态结构中, 称为路亚州

每个 Lua 状态都有一个或多个线程, 对应于独立、合作的执行路线。 类型 lua_State(尽管其名称)是指线程。 (间接地,通过线程,它也指 与线程关联的 Lua 状态。

指向线程的指针必须作为第一个参数传递给 库中的每个函数,除了lua_newstate, 从头开始创建一个 Lua 状态并返回一个指针 到处于新状态的主线程

4.1 – 堆栈

Lua 使用虚拟堆栈将值传入和传出 C。 此堆栈中的每个元素都表示一个 Lua 值 (、数字、字符串等)。 API 中的函数可以通过 他们收到的 Lua 状态参数。

每当 Lua 调用 C 时,被调用的函数都会得到一个新的堆栈, 它独立于以前的堆栈和堆栈 仍处于活动状态的 C 函数。 此堆栈最初包含 C 函数的任何参数 这是 C 函数可以存储临时的地方 Lua 重视并且必须推动其结果 返回给调用方(请参阅lua_CFunction)。

为方便起见, API 中的大多数查询操作不遵循严格的堆栈规则。 相反,它们可以引用堆栈中的任何元素 通过使用索引: 正指数表示绝对堆栈位置, 从 1 开始作为堆栈的底部; 负索引表示相对于堆栈顶部的偏移量。 更具体地说,如果堆栈有 n 个元素, 则索引 1 表示第一个元素 (即,首先推送到堆栈上的元素) 和 索引 n 表示最后一个元素; 索引 -1 也表示最后一个元素 (即顶部的元素) 索引 -n 表示第一个元素。

4.1.1 – Stack Size

When you interact with the Lua API, you are responsible for ensuring consistency. In particular, you are responsible for controlling stack overflow. When you call any API function, you must ensure the stack has enough room to accommodate the results.

There is one exception to the above rule: When you call a Lua function without a fixed number of results (see lua_call), Lua ensures that the stack has enough space for all results. However, it does not ensure any extra space. So, before pushing anything on the stack after such a call you should use lua_checkstack.

Whenever Lua calls C, it ensures that the stack has space for at least LUA_MINSTACK extra elements; that is, you can safely push up to values into it. is defined as 20, so that usually you do not have to worry about stack space unless your code has loops pushing elements onto the stack. Whenever necessary, you can use the function lua_checkstack to ensure that the stack has enough space for pushing new elements. LUA_MINSTACKLUA_MINSTACK

4.1.2 – Valid and Acceptable Indices

Any function in the API that receives stack indices works only with valid indices or acceptable indices.

valid index is an index that refers to a position that stores a modifiable Lua value. It comprises stack indices between 1 and the stack top () plus pseudo-indices, which represent some positions that are accessible to C code but that are not in the stack. Pseudo-indices are used to access the registry (see §4.3) and the upvalues of a C function (see §4.2). 1 ≤ abs(index) ≤ top

不需要特定可变位置的函数, 但只是一个值(例如,查询函数), 可以使用可接受的索引调用。 可接受的索引可以是任何有效的索引, 但它也可以是堆栈顶部之后的任何正指数 在为堆栈分配的空间内, 也就是说,索引最多达到堆栈大小。 (请注意,0 永远不是可接受的索引。 大于实数的升值指数(参见 §4.2) 当前 C 函数中的上行值也是可以接受的(但无效)。 除非另有说明, API 中的函数使用可接受的索引。

可接受的指数用于避免额外的测试 查询堆栈时针对堆栈顶部。 例如,C 函数可以查询其第三个参数 无需检查是否存在第三个参数, 也就是说,无需检查 3 是否为有效索引。

对于可以使用可接受的索引调用的函数, 任何无效的索引都被视为 包含虚拟类型的值LUA_TNONE, 其行为类似于 nil 值。

4.1.3 – 指向字符串的指针

API 返回指针中的几个函数 () 到 Lua 字符串在堆栈中。 (请参阅lua_pushfstringlua_pushlstring、lua_pushstring和lua_tolstring。 另见luaL_checklstringluaL_checkstring、 并在辅助库中luaL_tolstringconst char*

通常 Lua的垃圾收集可以释放或移动内部存储器 然后使指向内部字符串的指针失效。 为了允许安全使用这些指针, API 保证指向堆栈索引中字符串的任何指针 有效,但该索引处的字符串值未从堆栈中删除。 (不过,可以将其移动到另一个索引。 当索引是伪索引(指上值)时, 指针在相应调用处于活动状态时有效,并且 不会修改相应的上行值。

调试接口中的一些函数 还返回指向字符串的指针, 即lua_getlocal、lua_getupvalue、lua_setlocal和lua_setupvalue。 对于这些函数,指针保证 在调用方函数处于活动状态时有效,并且 给定的闭包(如果给定了一个)在堆栈中。

除了这些保证, 垃圾回收器可以自由失效 指向内部字符串的任何指针。

4.2 – C 闭包

创建 C 函数时, 可以将一些值与它相关联, 从而创建一个 C 闭包(见lua_pushcclosure); 这些值称为上值,它们是 每当调用函数时,都可以访问该函数。

每当调用 C 函数时, 其上升值位于特定的伪指数中。 这些伪索引由宏lua_upvalueindex生成。 与函数关联的第一个上值在索引处,依此类推。 对 的任何访问 , 其中 n 大于 当前函数 (但不大于 256, 这是闭包中最大上升值数的 <> 加), 生成可接受但无效的索引。lua_upvalueindex(1)lua_upvalueindex(n)

C 闭包也可以更改值 其相应的上值。

4.3 – 注册表

Lua 提供了一个注册表, 一个预定义的表,任何 C 代码都可以使用它来 存储它需要存储的任何 Lua 值。 注册表表始终可通过伪索引LUA_REGISTRYINDEX访问。 任何 C 库都可以将数据存储到此表中, 但必须注意选择键 与使用的不同 由其他库,以避免冲突。 通常,您应该使用包含库名称的字符串作为键, 或代码中带有 C 对象地址的轻量级用户数据, 或代码创建的任何 Lua 对象。 与变量名称一样, 字符串键以下划线开头,后跟 大写字母是为Lua保留的。

使用注册表中的整数键 通过参考机制(见luaL_ref) 以及一些预定义的值。 因此,注册表中的整数键 不得用于其他目的。

创建新的 Lua 状态时, 它的注册表带有一些预定义的值。 这些预定义值使用整数键编制索引 定义为 中的常量。 定义了以下常量:lua.h

  • LUA_RIDX_MAINTHREAD: 在此索引中,注册表具有 状态的主线。 (主线程是与状态一起创建的线程。
  • LUA_RIDX_GLOBALS: 在此索引中,注册表具有 全球环境。

4.4 – C 语言中的错误处理

在内部,Lua 使用 C 工具来处理错误。 (如果将 Lua 编译为 C++,它将使用异常; 在源代码中搜索以获取详细信息。 当Lua遇到任何错误时, 例如内存分配错误或类型错误, 它引发错误; 也就是说,它做跳远。 受保护的环境用于设置恢复点; 任何错误都会跳转到最近的活动恢复点。longjmpLUAI_THROWsetjmp

在 C 函数中,您可以显式引发错误 通过呼叫lua_error

API 中的大多数函数都可能引发错误, 例如,由于内存分配错误。 每个函数的文档指示是否 它可能会引发错误。

如果错误发生在任何受保护环境之外, Lua 调用 panic 函数(见lua_atpanic) 然后调用 , 从而退出主机应用程序。 您的紧急功能可以通过以下方式避免此退出 再也不回来了 (例如,跳远到Lua以外的恢复点)。abort

恐慌函数, 顾名思义, 是最后的手段。 程序应避免它。 作为一般规则, 当 Lua 以 Lua 状态调用 C 函数时, 它可以在那个Lua状态上做任何它想做的事情, 因为它应该已经受到保护。 然而 当 C 代码在其他 Lua 状态上运行时 (例如,函数的 Lua 状态参数, 存储在注册表中的 Lua 状态,或 lua_newthread)的结果) 它应该只在不会引发错误的 API 调用中使用它们。

panic 函数像消息处理程序一样运行(参见 §2.3); 特别是,错误对象位于堆栈的顶部。 但是,不能保证堆栈空间。 要在堆栈上推送任何内容, panic 函数必须首先检查可用空间(参见 §4.1.1)。

4.4.1 – 状态码

在 API 中报告错误的几个函数使用以下函数 指示不同类型的错误或其他情况的状态代码:

  • LUA_OK (0):无错误。
  • LUA_ERRRUN运行时错误。
  • LUA_ERRMEM内存分配错误。 对于此类错误,Lua 不会调用消息处理程序。
  • LUA_ERRERR运行消息处理程序时出错。
  • LUA_ERRSYNTAX预编译期间的语法错误。
  • LUA_YIELD线程(协程)产生。
  • LUA_ERRFILE与文件相关的错误; 例如,它无法打开或读取文件。

这些常量在头文件 中定义。lua.h

4.5 – C 语言中的处理产量

在内部,Lua 使用 C 工具来生成协程。 因此,如果 C 函数调用 API 函数 并且此 API 函数产生 (直接或间接通过调用另一个产生函数), 路亚再也回不去了, 因为 从 C 堆栈中删除了它的帧。longjmpfoofoolongjmp

为了避免这种问题, Lua 每当尝试在 API 调用中屈服时都会引发错误, 除了三个功能:lua_yieldk、lua_callk和lua_pcallk。 所有这些函数都接收一个延续函数(作为名为 的参数),以便在产生后继续执行。k

我们需要设置一些术语来解释延续。 我们有一个从Lua调用的C函数,我们将调用它 原始函数。 然后,此原始函数在 C API 中调用这三个函数之一, 我们将调用被调用方函数, 然后生成当前线程。 当被调用方函数lua_yieldk时,可能会发生这种情况, 或者当被调用方函数lua_callk或lua_pcallk并且它们调用的函数生成时。

假设正在运行的线程在执行被调用方函数时产生。 线程恢复后, 它最终将完成被调用方函数的运行。 然而 被调用方函数无法返回到原始函数, 因为它在C堆栈中的框架被屈服破坏了。 相反,Lua 调用了一个延续函数, 它是作为被调用方函数的参数给出的。 顾名思义, 延续函数应继续执行任务 的原始功能。

作为说明,请考虑以下函数:

     int original_function (lua_State *L) {
       ...     /* code 1 */
       status = lua_pcall(L, n, m, h);  /* calls Lua */
       ...     /* code 2 */
     }

现在我们要允许 由 lua_pcall 运行的 Lua 代码产生。 首先,我们可以像下面这样重写我们的函数:

     int k (lua_State *L, int status, lua_KContext ctx) {
       ...  /* code 2 */
     }
     
     int original_function (lua_State *L) {
       ...     /* code 1 */
       return k(L, lua_pcall(L, n, m, h), ctx);
     }

在上面的代码中, 新函数是一个延续函数(类型为 lua_KFunction), 哪个应该完成原始功能的所有工作 打电话给lua_pcall后正在做。 现在,我们必须通知 Lua,如果 Lua 代码,它必须调用 被lua_pcall执行会以某种方式被打断 (误差或屈服), 所以我们重写代码,如下所示, 将lua_pcall替换为lua_pcallk:kk

     int original_function (lua_State *L) {
       ...     /* code 1 */
       return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1);
     }

请注意对延续的外部显式调用: Lua 将仅在需要时调用延续,即 如果出现错误或在产量后恢复。 如果被调用的函数正常返回而不屈服,则lua_pcallk(和lua_callk)也将正常返回。 (当然,在这种情况下,与其调用延续, 您可以直接在原始函数中执行等效的工作。

除了卢阿州, 延续函数还有另外两个参数: 调用的最终状态和上下文值 () 最初传给lua_pcallk。 Lua 不使用此上下文值; 它仅将此值从原始函数传递到 延续功能。 对于lua_pcallk, 状态与 lua_pcallk 返回的值相同, 除了在收益率后执行时LUA_YIELD (而不是LUA_OK)。 对于lua_yieldk和lua_callk, 当 Lua 调用延续时,状态始终LUA_YIELD。 (对于这两个函数, Lua 不会在出现错误时调用延续, 因为它们不处理错误。 同样,在使用lua_callk时, 你应该调用延续函数 以LUA_OK作为状态。 (对于lua_yieldk来说,打电话没有多大意义 直接延续函数, 因为lua_yieldk通常不会返回。ctx

Lua 将延续函数视为原始函数。 延续函数接收相同的 Lua 堆栈 从原始函数来看, 在相同的状态下,如果被调用方函数已返回。 (例如, lua_callk后,函数及其参数为 从堆栈中删除并替换为调用的结果。 它也具有相同的上升值。 无论它返回什么,Lua 都会像返回一样处理它 的原始功能。

4.6 – 函数和类型

在这里,我们列出了 C API 中的所有函数和类型 按字母顺序排列。 每个函数都有一个如下所示的指标:[-o, +p, x]

第一个字段, 是函数从堆栈中弹出的元素数。 第二个字段, , 是函数推送到堆栈上的元素数。 (任何函数总是在弹出其参数后推送其结果。 表单中的字段表示函数可以推送(或弹出)或元素, 视情况而定; 询问标记“”表示 我们无法知道函数弹出/推送了多少个元素 只看它的论点。 (例如,它们可能取决于堆栈中的内容。 第三个字段, , 告知函数是否可能引发错误: '' 表示函数永远不会引发任何错误; “”表示函数可能仅引发内存不足错误; '' 表示函数可能会引发文本中解释的错误; '' 表示函数可以运行任意 Lua 代码, 直接或通过元方法, 因此可能会引发任何错误。opx|yxy?x-mve

lua_absindex

[-0, +0, –]

int lua_absindex (lua_State *L, int idx);

将可接受的索引转换为等效的绝对索引 (即,不依赖于堆栈大小的堆栈)。idx

lua_Alloc

typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);

Lua 状态使用的内存分配函数的类型。 分配器函数必须提供 功能类似于 , 但不完全相同。 它的参数是,一个传递给lua_newstate的不透明指针;,指向正在分配/重新分配/释放的块的指针;,块的原始大小或一些关于什么的代码 正在分配; 和,块的新大小。reallocudptrosizensize

当不是时,是块的大小由 , 也就是说,分配或重新分配时给定的大小。ptrNULLosizeptr

When is 对 Lua 正在分配的对象类型进行编码。 是LUA_TSTRINGLUA_TTABLELUA_TFUNCTIONLUA_TUSERDATALUA_TTHREAD中的任何一个(且仅在何时) Lua 正在创建该类型的新对象。 什么时候是其他值, Lua正在为其他东西分配内存。ptrNULLosizeosizeosize

Lua 假定分配器函数具有以下行为:

当为零时, 分配器必须表现得像,然后返回。nsizefreeNULL

当不为零时, 分配器的行为必须类似于 。 特别是,分配器返回当且仅当它无法满足请求时。nsizereallocNULL

下面是分配器函数的简单实现。 它由luaL_newstate在辅助库中使用。

     static void *l_alloc (void *ud, void *ptr, size_t osize,
                                                size_t nsize) {
       (void)ud;  (void)osize;  /* not used */
       if (nsize == 0) {
         free(ptr);
         return NULL;
       }
       else
         return realloc(ptr, nsize);
     }

请注意,ISO C 确保 这没有效果,这相当于 .free(NULL)realloc(NULL,size)malloc(size)

lua_arith

[-(2|1), +1, e]

void lua_arith (lua_State *L, int op);

对两个值执行算术运算或按位运算 (或一个,在否定的情况下) 在堆栈的顶部, 顶部的值是第二个操作数, 弹出这些值,并推送操作的结果。 该函数遵循相应 Lua 运算符的语义 (也就是说,它可以调用元方法)。

的值必须是以下常量之一:op

  • LUA_OPADD执行加法(+)
  • LUA_OPSUB执行减法(-)
  • LUA_OPMUL执行乘法(*)
  • LUA_OPDIV执行浮点除法 (/)
  • LUA_OPIDIV执行楼层划分(//)
  • LUA_OPMOD执行模 (%)
  • LUA_OPPOW执行幂运算 (^)
  • LUA_OPUNM执行数学否定(一元)-)
  • LUA_OPBNOT按位执行 NOT (~)
  • LUA_OPBAND按位执行 AND (&)
  • LUA_OPBOR执行按位 OR (|)
  • LUA_OPBXOR执行按位独占 OR (~)
  • LUA_OPSHL执行左移(<<)
  • LUA_OPSHR执行右移(>>)

lua_atpanic

[-0, +0, –]

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);

设置新的 panic 函数并返回旧的 panic 函数(参见 §4.4)。

lua_call

[-(nargs+1), +nresults, e]

void lua_call (lua_State *L, int nargs, int nresults);

调用函数。 像常规的 Lua 调用一样,尊重元方法。 所以,这里的“功能”这个词 表示任何可调用的价值。lua_call__call

要进行调用,您必须使用以下协议: 首先,将要调用的函数推送到堆栈上; 然后,将参数推送到调用 直接排序; 也就是说,第一个参数首先被推送。 最后你打电话给lua_call; 是推送到堆栈上的参数数。 当函数返回时, 弹出所有参数和函数值 并将调用结果推送到堆栈上。 结果数调整为 , 除非是LUA_MULTRET。 在这种情况下,将推送函数的所有结果; Lua 负责确保返回的值适合堆栈空间, 但它不能确保堆栈中有任何额外的空间。 函数结果按直接顺序推送到堆栈上 (第一个结果先推), 这样在调用之后,最后一个结果位于堆栈的顶部。nargsnresultsnresults

调用和运行函数时的任何错误都会向上传播 (带 )。longjmp

以下示例显示主机程序如何执行 等效于这个 Lua 代码:

     a = f("how", t.x, 14)

这是在 C 中:

     lua_getglobal(L, "f");                  /* function to be called */
     lua_pushliteral(L, "how");                       /* 1st argument */
     lua_getglobal(L, "t");                    /* table to be indexed */
     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
     lua_remove(L, -2);                  /* remove 't' from the stack */
     lua_pushinteger(L, 14);                          /* 3rd argument */
     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
     lua_setglobal(L, "a");                         /* set global 'a' */

请注意,上面的代码是平衡的: 在其结束时,堆栈将恢复到其原始配置。 这被认为是良好的编程实践。

lua_callk

[-(nargs + 1), +nresults, e]

void lua_callk (lua_State *L,
                int nargs,
                int nresults,
                lua_KContext ctx,
                lua_KFunction k);

此函数的行为与lua_call完全相同, 但允许被调用的函数产生(参见 §4.5)。

lua_CFunction

typedef int (*lua_CFunction) (lua_State *L);

C 函数的类型。

为了与Lua正确沟通, C 函数必须使用以下协议, 它定义了参数和结果的传递方式: C 函数从其堆栈中的 Lua 接收其参数 按直接顺序(首先推送第一个参数)。 因此,当函数启动时,返回函数接收的参数数。 第一个参数(如果有)位于索引 1 处 它的最后一个参数在索引。 为了将值返回给 Lua,C 函数只需将它们推送到堆栈上, 按直接顺序(首先推送第一个结果), 并在 C 中返回结果数。 结果下方堆栈中的任何其他值都将正确 被路亚丢弃。 与Lua函数一样,Lua调用的C函数也可以返回 许多结果。lua_gettop(L)lua_gettop(L)

例如,以下函数接收一个可变数字 数字参数,并返回其平均值和总和:

     static int foo (lua_State *L) {
       int n = lua_gettop(L);    /* number of arguments */
       lua_Number sum = 0.0;
       int i;
       for (i = 1; i <= n; i++) {
         if (!lua_isnumber(L, i)) {
           lua_pushliteral(L, "incorrect argument");
           lua_error(L);
         }
         sum += lua_tonumber(L, i);
       }
       lua_pushnumber(L, sum/n);        /* first result */
       lua_pushnumber(L, sum);         /* second result */
       return 2;                   /* number of results */
     }

lua_checkstack

[-0, +0, –]

int lua_checkstack (lua_State *L, int n);

确保堆栈至少有空间容纳额外的元素, 也就是说,您可以安全地将值推送到其中。 如果它无法满足请求,则返回 false, 要么是因为它会导致堆栈 大于固定的最大大小 (通常至少几千个元素)或 因为它无法为额外的空间分配内存。 此函数从不缩小堆栈; 如果堆栈已经有空间容纳额外的元素, 它保持不变。nn

lua_close

[-0, +0, –]

void lua_close (lua_State *L);

关闭主线程中所有活动的待关闭变量, 释放给定 Lua 状态的所有对象 (调用相应的垃圾收集元方法,如果有的话), 并释放此状态使用的所有动态内存。

在多个平台上,您可能不需要调用此函数, 因为当宿主程序结束时,所有资源都会自然释放。 另一方面,创建多个状态的长时间运行的程序, 例如守护程序或 Web 服务器, 可能需要在不需要状态时立即关闭状态。

lua_closeslot

[-0, +0, e]

void lua_closeslot (lua_State *L, int index);

关闭给定索引处要关闭的插槽,并将其值设置为 nil。 索引必须是之前标记为关闭的最后一个索引 (请参阅lua_toclose)仍处于活动状态(即尚未关闭)。

元方法不能产生 通过此函数调用时。__close

(此功能在版本 5.4.3 中引入。

lua_closethread

[-0, +?, –]

int lua_closethread (lua_State *L, lua_State *from);

重置线程,清理其调用堆栈并关闭所有挂起 待闭合变量。 返回状态代码:LUA_OK表示线程中没有错误 (停止线程的原始错误或 关闭方法的错误), 否则为错误状态。 如果出现错误, 将错误对象保留在堆栈的顶部。

该参数表示正在重置 的协程。 如果没有这样的协程, 此参数可以是 。fromLNULL

(此功能在版本 5.4.6 中引入。

lua_compare

[-0, +0, e]

int lua_compare (lua_State *L, int index1, int index2, int op);

比较两个 Lua 值。 如果索引处的值与索引处的值相比满足 1 , 遵循相应 Lua 运算符的语义 (也就是说,它可以调用元方法)。 否则返回 0。 如果任何索引无效,则返回 0。index1opindex2

的值必须是以下常量之一:op

  • LUA_OPEQ比较相等 (==)
  • LUA_OPLT比较小于 (<)
  • LUA_OPLE比较小于或等于 (<=)

lua_concat

[-n, +1, e]

void lua_concat (lua_State *L, int n);

连接堆栈顶部的值, 弹出它们,并将结果留在顶部。 如果为 1,则结果是堆栈上的单个值 (即,该函数不执行任何操作); 如果为 0,则结果为空字符串。 串联按照 Lua 的通常语义执行 (参见 §3.4.6)。nnn

lua_copy

[-0, +0, –]

void lua_copy (lua_State *L, int fromidx, int toidx);

将索引处的元素复制到有效索引中, 替换该位置的值。 其他位置的值不受影响。fromidxtoidx

lua_createtable

[-0, +1, ]

void lua_createtable (lua_State *L, int narr, int nrec);

创建一个新的空表并将其推送到堆栈上。 参数是表有多少个元素的提示 将作为一个序列; 参数是有多少其他元素的提示 该表将具有。 Lua 可以使用这些提示为新表预分配内存。 当您提前知道时,此预分配可能有助于性能 表将具有多少个元素。 否则,您可以使用函数lua_newtablenarrnrec

lua_dump

[-0, +0, –]

int lua_dump (lua_State *L,
                        lua_Writer writer,
                        void *data,
                        int strip);

将函数转储为二进制块。 在堆栈顶部接收 Lua 函数 并产生一个二进制块, 如果再次加载, 生成一个等效于转储的函数。 当它产生部分块时,lua_dump调用函数(见lua_Writer) 用给定的来写它们。writerdata

如果为真, 二进制表示形式可能不包括所有调试信息 关于函数, 以节省空间。strip

返回的值是最后一个返回的错误代码 打电话给作家; 0 表示没有错误。

此函数不会从堆栈中弹出 Lua 函数。

lua_error

[-1, +0, v]

int lua_error (lua_State *L);

引发 Lua 错误, 使用堆栈顶部的值作为错误对象。 这个函数做跳远, 因此永远不会返回 (见luaL_error)。

lua_gc

[-0, +0, –]

int lua_gc (lua_State *L, int what, ...);

控制垃圾回收器。

此函数执行多项任务, 根据参数的值。 对于需要额外参数的选项, 它们列在选项之后。what

  • LUA_GCCOLLECT: 执行完整的垃圾收集周期。
  • LUA_GCSTOP: 停止垃圾回收器。
  • LUA_GCRESTART: 重新启动垃圾回收器。
  • LUA_GCCOUNT: 返回 Lua 正在使用的当前内存量(以 KB 为单位)。
  • LUA_GCCOUNTB: 返回除以当前字节数的余数 Lua 在 1024 年使用的内存。
  • LUA_GCSTEP(整数步长): 执行垃圾回收的增量步骤, 对应于千字节的分配。stepsize
  • LUA_GCISRUNNING: 返回一个布尔值,该值指示收集器是否正在运行 (即,未停止)。
  • LUA_GCINC (int pause, int stepmul, stepsize): 将收集器更改为增量模式 使用给定的参数(参见 §2.5.1)。 返回上一个模式( 或 )。LUA_GCGENLUA_GCINC
  • LUA_GCGEN (int minormul, int majormul): 将收集器更改为分代模式 使用给定参数(参见 §2.5.2)。 返回上一个模式( 或 )。LUA_GCGENLUA_GCINC

有关这些选项的更多详细信息, 请参阅收集垃圾

此函数不应由终结器调用。

lua_getallocf

[-0, +0, –]

lua_Alloc lua_getallocf (lua_State *L, void **ud);

返回给定状态的内存分配函数。 如果不是,Lua 存储在 设置内存分配器函数时给出的不透明指针。udNULL*ud

lua_getfield

[-0, +1, e]

int lua_getfield (lua_State *L, int index, const char *k);

将值推到堆栈上, 其中 是给定索引处的值。 与 Lua 一样,此函数可能会触发元方法 对于“索引”事件(参见 §2.4)。t[k]t

返回推送值的类型。

lua_getextraspace

[-0, +0, –]

void *lua_getextraspace (lua_State *L);

返回指向与 给定路亚状态。 应用程序可以将此区域用于任何目的; Lua 不使用它做任何事情。

每个新线程都使用此副本初始化此区域 主螺纹的面积。

默认情况下,此区域的大小相当于指向 void 的指针, 但是您可以为此区域重新编译具有不同大小的Lua。 (请参阅。)LUA_EXTRASPACEluaconf.h

lua_getglobal

[-0, +1, e]

int lua_getglobal (lua_State *L, const char *name);

将全局 的值推送到堆栈上。 返回该值的类型。name

lua_geti

[-0, +1, e]

int lua_geti (lua_State *L, int index, lua_Integer i);

将值推到堆栈上, 其中 是给定索引处的值。 与 Lua 一样,此函数可能会触发元方法 对于“索引”事件(参见 §2.4)。t[i]t

返回推送值的类型。

lua_getmetatable

[-0, +(0|1), –]

int lua_getmetatable (lua_State *L, int index);

如果给定索引处的值具有元表, 该函数将该元表推送到堆栈上并返回 1。 否则 该函数返回 0 并在堆栈上推送任何内容。

lua_gettable

[-1, +1, e]

int lua_gettable (lua_State *L, int index);

将值推到堆栈上, 给定索引处的值在哪里 并且是堆栈顶部的值。t[k]tk

此函数从堆栈中弹出密钥, 将结果值推到其位置。 与 Lua 一样,此函数可能会触发元方法 对于“索引”事件(参见 §2.4)。

返回推送值的类型。

lua_gettop

[-0, +0, –]

int lua_gettop (lua_State *L);

返回堆栈中顶部元素的索引。 因为索引从 1 开始, 此结果等于堆栈中的元素数; 特别是,0 表示空堆栈。

lua_getiuservalue

[-0, +1, –]

int lua_getiuservalue (lua_State *L, int index, int n);

将与 给定索引的完整用户数据,以及 返回推送值的类型。n

如果用户数据没有该值, 推零并返回LUA_TNONE。

lua_insert

[-1, +1, –]

void lua_insert (lua_State *L, int index);

将顶部元素移动到给定的有效索引中, 将这个索引上方的元素向上移动到开放空间。 此函数不能使用伪索引调用, 因为伪索引不是实际的堆栈位置。

lua_Integer

typedef ... lua_Integer;

Lua 中的整数类型。

默认情况下,此类型为 、 (通常是 64 位双补码整数), 但可以更改为 OR(通常是 32 位双补码整数)。 (请参阅。)long longlongintLUA_INT_TYPEluaconf.h

Lua 还定义了常量LUA_MININTEGERLUA_MAXINTEGER, 具有适合此类型的最小值和最大值。

lua_isboolean

[-0, +0, –]

int lua_isboolean (lua_State *L, int index);

如果给定索引处的值是布尔值,则返回 1, 否则为 0。

lua_iscfunction

[-0, +0, –]

int lua_iscfunction (lua_State *L, int index);

如果给定索引处的值是 C 函数,则返回 1, 否则为 0。

lua_isfunction

[-0, +0, –]

int lua_isfunction (lua_State *L, int index);

如果给定索引处的值是函数,则返回 1 (C 或 Lua),否则为 0。

lua_isinteger

[-0, +0, –]

int lua_isinteger (lua_State *L, int index);

如果给定索引处的值是整数,则返回 1 (即,该值是一个数字,表示为整数), 否则为 0。

lua_islightuserdata

[-0, +0, –]

int lua_islightuserdata (lua_State *L, int index);

如果给定索引处的值是轻用户数据,则返回 1, 否则为 0。

lua_isnil

[-0, +0, –]

int lua_isnil (lua_State *L, int index);

如果给定索引处的值为 nil,则返回 1, 否则为 0。

lua_isnone

[-0, +0, –]

int lua_isnone (lua_State *L, int index);

如果给定索引无效,则返回 1, 否则为 0。

lua_isnoneornil

[-0, +0, –]

int lua_isnoneornil (lua_State *L, int index);

如果给定索引无效,则返回 1 或者,如果此索引处的值为, 否则为 0。

lua_isnumber

[-0, +0, –]

int lua_isnumber (lua_State *L, int index);

如果给定索引处的值是数字,则返回 1 或可转换为数字的字符串, 否则为 0。

lua_isstring

[-0, +0, –]

int lua_isstring (lua_State *L, int index);

如果给定索引处的值是字符串,则返回 1 或数字(始终可转换为字符串), 否则为 0。

lua_istable

[-0, +0, –]

int lua_istable (lua_State *L, int index);

如果给定索引处的值是表,则返回 1, 否则为 0。

lua_isthread

[-0, +0, –]

int lua_isthread (lua_State *L, int index);

如果给定索引处的值是线程,则返回 1, 否则为 0。

lua_isuserdata

[-0, +0, –]

int lua_isuserdata (lua_State *L, int index);

如果给定索引处的值是用户数据,则返回 1 (全色或浅色),否则为 0。

lua_isyieldable

[-0, +0, –]

int lua_isyieldable (lua_State *L);

如果给定的协程可以产生, 否则为 1。

lua_KContext

typedef ... lua_KContext;

延续函数上下文的类型。 它必须是数值类型。 此类型定义为何时可用, 这样它也可以存储指针。 否则,它被定义为 。intptr_tintptr_tptrdiff_t

lua_KFunction

typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);

延续函数的类型(参见 §4.5)。

lua_len

[-0, +1, e]

void lua_len (lua_State *L, int index);

返回给定索引处值的长度。 它等效于 Lua 中的 '' 运算符(参见 §3.4.7)和 可能会触发“长度”事件的元方法(参见 §2.4)。 结果被推送到堆栈上。#

lua_load

[-0, +1, –]

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname,
              const char *mode);

加载 Lua 块而不运行它。 如果没有错误,则将编译后的块推送为 Lua 堆栈顶部的功能。 否则,它会推送错误消息。lua_load

该函数使用用户提供的函数 以读取块(请参阅lua_Reader)。 参数是传递给读取器函数的不透明值。lua_loadreaderdata

该参数为块命名, 用于错误消息和调试信息(参见 §4.7)。chunkname

lua_load自动检测区块是文本还是二进制 并相应地加载它(请参阅程序)。 字符串的工作方式与函数加载一样, 加上 值等效于字符串 “”。luacmodeNULLbt

lua_load uses the stack internally, so the reader function must always leave the stack unmodified when returning.

lua_load can return LUA_OK, LUA_ERRSYNTAX, or LUA_ERRMEM. The function may also return other values corresponding to errors raised by the read function (see §4.4.1).

If the resulting function has upvalues, its first upvalue is set to the value of the global environment stored at index in the registry (see §4.3). When loading main chunks, this upvalue will be the variable (see §2.2). Other upvalues are initialized with nilLUA_RIDX_GLOBALS_ENV

lua_newstate

[-0, +0, –]

lua_State *lua_newstate (lua_Alloc f, void *ud);

Creates a new independent state and returns its main thread. Returns if it cannot create the state (due to lack of memory). The argument is the allocator function; Lua will do all memory allocation for this state through this function (see lua_Alloc). The second argument, , is an opaque pointer that Lua passes to the allocator in every call. NULLfud

lua_newtable

[-0, +1, m]

void lua_newtable (lua_State *L);

Creates a new empty table and pushes it onto the stack. It is equivalent to . lua_createtable(L, 0, 0)

lua_newthread

[-0, +1, m]

lua_State *lua_newthread (lua_State *L);

Creates a new thread, pushes it on the stack, and returns a pointer to a lua_State that represents this new thread. The new thread returned by this function shares with the original thread its global environment, but has an independent execution stack.

Threads are subject to garbage collection, like any Lua object.

lua_newuserdatauv

[-0, +1, ]

void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue);

此函数在堆栈上创建并推送一个新的完整用户数据, 与关联的 Lua 值相关联,称为 , 加上带有字节的关联原始内存块。 (可以使用函数lua_setiuservalue和lua_getiuservalue设置和读取用户值。nuvalueuser valuessize

该函数返回内存块的地址。 Lua 确保此地址只要有效 相应的用户数据是有效的(参见§2.5)。 此外,如果用户数据被标记为最终确定(参见§2.5.3), 它的地址至少在调用其终结器之前是有效的。

lua_next

[-1, +(2|0), v]

int lua_next (lua_State *L, int index);

从堆栈中弹出一个键, 并从给定索引处的表中推送一个键值对, 给定键之后的“下一个”对。 如果表中没有更多元素, 然后lua_next返回 0 并且不推送任何内容。

典型的表遍历如下所示:

     /* table is in the stack at index 't' */
     lua_pushnil(L);  /* first key */
     while (lua_next(L, t) != 0) {
       /* uses 'key' (at index -2) and 'value' (at index -1) */
       printf("%s - %s\n",
              lua_typename(L, lua_type(L, -2)),
              lua_typename(L, lua_type(L, -1)));
       /* removes 'value'; keeps 'key' for next iteration */
       lua_pop(L, 1);
     }

遍历表时, 避免直接在按键上呼叫lua_tolstring, 除非您知道密钥实际上是一个字符串。 回想一下,lua_tolstring可能会改变 给定索引处的值; 这会混淆下一个对lua_next的调用。

如果给定的键,此函数可能会引发错误 既不为零,也不存在于表中。 有关修改的注意事项,请参阅下面的函数 遍历期间的表。

lua_Number

typedef ... lua_Number;

Lua中的浮标类型。

默认情况下,此类型为双精度, 但这可以更改为单浮点数或长双精度数。 (请参阅。)LUA_FLOAT_TYPEluaconf.h

lua_numbertointeger

int lua_numbertointeger (lua_Number n, lua_Integer *p);

尝试将 Lua 浮点数转换为 Lua 整数; 浮点数必须具有整数值。 如果该值在 Lua 整数范围内, 它被转换为整数并分配给 。 宏生成一个布尔值,指示是否 转换成功。 (请注意,此范围测试可能很难进行 由于舍入,没有此宏正确。n*p

此宏可以多次计算其参数。

lua_pcall

[-(nargs + 1), +(nresults|1), –]

int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);

在保护模式下调用函数(或可调用对象)。

两者的含义相同 在lua_call。 如果在调用过程中没有错误,则lua_pcall的行为与lua_call完全相同。 但是,如果有任何错误,lua_pcall会捕获它, 在堆栈(错误对象)上推送单个值, 并返回错误代码。 像lua_call一样,lua_pcall总是删除函数 及其来自堆栈的参数。nargsnresults

如果为 0, 然后返回堆栈上的错误对象 正是原始错误对象。 否则,是消息处理程序的堆栈索引。 (此索引不能是伪索引。 如果出现运行时错误, 此处理程序将使用错误对象调用 它的返回值将是对象 由 lua_pcall 返回堆栈。msghmsgh

通常,消息处理程序用于添加更多调试 错误对象的信息,例如堆栈回溯。 lua_pcall返回后无法收集此类信息, 因为到那时堆栈已经解开了。

lua_pcall 函数返回以下状态代码之一:LUA_OK、LUA_ERRRUN、LUA_ERRMEM或LUA_ERRERR。

lua_pcallk

[-(nargs + 1), +(nresults|1), –]

int lua_pcallk (lua_State *L,
                int nargs,
                int nresults,
                int msgh,
                lua_KContext ctx,
                lua_KFunction k);

此函数的行为与lua_pcall完全相同, 除了它允许被调用的函数产生(参见§4.5)。

lua_pop

[-n, +0, e]

void lua_pop (lua_State *L, int n);

从堆栈中弹出元素。 它是作为lua_settop上的宏实现的。n

lua_pushboolean

[-0, +1, –]

void lua_pushboolean (lua_State *L, int b);

将带有值的布尔值推送到堆栈上。b

lua_pushcclosure

[-n, +1, m]

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);

将新的 C 闭包推送到堆栈上。 此函数接收指向 C 函数的指针 并将 Lua 类型的 Lua 值推送到堆栈上, 调用时,调用相应的 C 函数。 该参数告诉此函数将有多少个上升值 (见§4.2)。functionn

Lua 可调用的任何函数都必须 按照正确的协议接收其参数 并返回其结果(请参阅lua_CFunction)。

创建 C 函数时, 可以将一些值与它相关联, 所谓的上升值; 然后,每当调用函数时,函数都可以访问这些上行值。 这种关联称为 C 闭包(参见 §4.2)。 要创建 C 闭包, 首先,必须将其上行值的初始值推送到堆栈上。 (当有多个上升值时,首先推送第一个值。 然后调用lua_pushcclosure来创建 C 函数并将其推送到堆栈上, 参数告诉将有多少个值 与函数相关联。lua_pushcclosure还会从堆栈中弹出这些值。n

的最大值为 255。n

当为零时, 此函数创建一个轻 C 函数, 它只是一个指向 C 函数的指针。 在这种情况下,它永远不会引发内存错误。n

lua_pushcfunction

[-0, +1, –]

void lua_pushcfunction (lua_State *L, lua_CFunction f);

将 C 函数推送到堆栈上。 此函数等效于没有上值的lua_pushcclosure。

lua_pushfstring

[-0, +1, v]

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

将格式化字符串推送到堆栈上 并返回指向此字符串的指针(请参阅 §4.1.3)。 它类似于ISO C函数, 但有两个重要的区别。 第一 您不必为结果分配空间; 结果是一个 Lua 字符串,Lua 负责内存分配 (以及通过垃圾回收解除分配)。 第二 转换说明符受到很大限制。 没有标志、宽度或精度。 转换说明符只能是 “”(插入字符“”), ''(插入以零结尾的字符串,没有大小限制), ''(插入lua_Number), ''(插入lua_Integer), ''(插入指针), “”(插入一个), ''(插入 a 作为单字节字符),以及 ''(插入 作为 UTF-8 字节序列)。sprintf%%%%s%f%I%p%dint%cint%Ulong int

此函数可能会由于内存溢出而引发错误 或无效的转化说明符。

lua_pushglobaltable

[-0, +1, –]

void lua_pushglobaltable (lua_State *L);

将全局环境推送到堆栈上。

lua_pushinteger

[-0, +1, –]

void lua_pushinteger (lua_State *L, lua_Integer n);

将带有值的整数推送到堆栈上。n

lua_pushlightuserdata

[-0, +1, –]

void lua_pushlightuserdata (lua_State *L, void *p);

将轻量级用户数据推送到堆栈上。

用户数据表示 Lua 中的 C 值。 浅用户数据表示指针,即 . 它是一个值(如数字): 你不创建它,它没有单独的元表, 并且它不会被收集(因为它从未被创建过)。 轻用户数据等于“任意” 具有相同 C 地址的轻用户数据。void*

lua_pushliteral

[-0, +1, ]

const char *lua_pushliteral (lua_State *L, const char *s);

此宏等效于 lua_pushstring, 但应仅在是文本字符串时使用。 (Lua 可能会优化这种情况。s

lua_pushlstring

[-0, +1, ]

const char *lua_pushlstring (lua_State *L, const char *s, size_t len);

将大小指向的字符串推到堆栈上。 Lua 将制作或重用给定字符串的内部副本, 因此,内存可以立即释放或重复使用 函数返回。 字符串可以包含任何二进制数据, 包括嵌入的零。slens

返回指向字符串的内部副本的指针(请参阅 §4.1.3)。

lua_pushnil

[-0, +1, –]

void lua_pushnil (lua_State *L);

将 nil 值推送到堆栈上。

lua_pushnumber

[-0, +1, –]

void lua_pushnumber (lua_State *L, lua_Number n);

将具有值的浮点数推送到堆栈上。n

lua_pushstring

[-0, +1, ]

const char *lua_pushstring (lua_State *L, const char *s);

将指向 的零终止字符串推送到堆栈上。 Lua 将制作或重用给定字符串的内部副本, 因此,内存可以立即释放或重复使用 函数返回。ss

返回指向字符串的内部副本的指针(请参阅 §4.1.3)。

如果是 ,则推 nil 并返回 。sNULLNULL

lua_pushthread

[-0, +1, –]

int lua_pushthread (lua_State *L);

将 表示的线程推送到堆栈上。 如果此线程是其状态的主线程,则返回 1。L

lua_pushvalue

[-0, +1, –]

void lua_pushvalue (lua_State *L, int index);

在给定索引处推送元素的副本 到堆栈上。

lua_pushvfstring

[-0, +1, v]

const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);

等效于 lua_pushfstring,只是它接收的参数数量而不是可变数量的参数。va_list

lua_rawequal

[-0, +0, –]

int lua_rawequal (lua_State *L, int index1, int index2);

如果索引中的两个值原始相等,则返回 1 (即,相等而不调用元方法)。 否则返回 0。 如果任何索引无效,则返回 0。index1index2__eq

lua_rawget

[-1, +1, –]

int lua_rawget (lua_State *L, int index);

与lua_gettable类似,但进行原始访问 (即,没有元方法)。 at 的值必须是表。index

lua_rawgeti

[-0, +1, –]

int lua_rawgeti (lua_State *L, int index, lua_Integer n);

将值推到堆栈上, 给定索引处的表在哪里。 访问是原始的, 也就是说,它不使用元值。t[n]t__index

返回推送值的类型。

lua_rawgetp

[-0, +1, –]

int lua_rawgetp (lua_State *L, int index, const void *p);

将值推到堆栈上, 其中 是给定索引处的表,是表示为轻用户数据的指针。 访问权限是原始的; 也就是说,它不使用元值。t[k]tkp__index

返回推送值的类型。

lua_rawlen

[-0, +0, –]

lua_Unsigned lua_rawlen (lua_State *L, int index);

返回给定索引处值的原始“长度”: 对于字符串,这是字符串长度; 对于表,这是长度运算符 ('') 的结果 没有元方法; 对于用户数据,这是分配的内存块的大小 对于用户数据。 对于其他值,此调用返回 0。#

lua_rawset

[-2, +0, ]

void lua_rawset (lua_State *L, int index);

lua_settable类似,但执行原始分配 (即,没有元方法)。 at 的值必须是表。index

lua_rawseti

[-1, +0, ]

void lua_rawseti (lua_State *L, int index, lua_Integer i);

等效于 , 给定索引处的表在哪里 并且是堆栈顶部的值。t[i] = vtv

此函数从堆栈中弹出值。 作业是原始的, 也就是说,它不使用元值。__newindex

lua_rawsetp

[-1, +0, ]

void lua_rawsetp (lua_State *L, int index, const void *p);

等效于 , 其中,给定索引处的表,被编码为轻用户数据, 并且是堆栈顶部的值。t[p] = vtpv

此函数从堆栈中弹出值。 作业是原始的, 也就是说,它不使用元值。__newindex

lua_Reader

typedef const char * (*lua_Reader) (lua_State *L,
                                    void *data,
                                    size_t *size);

lua_load使用的读取器函数。 每当lua_load需要另一块块时, 它呼唤读者, 传递其参数。 读取器必须返回指向内存块的指针 用一块新的块 并设置为块大小。 在再次调用读取器函数之前,该块必须存在。 为了表示块的结束, 读取器必须返回或设置为零。 读取器函数可以返回大于零的任何大小的片段。datasizeNULLsize

lua_register

[-0, +0, e]

void lua_register (lua_State *L, const char *name, lua_CFunction f);

将 C 函数设置为全局 的新值。 它被定义为一个宏:fname

     #define lua_register(L,n,f) \
            (lua_pushcfunction(L, f), lua_setglobal(L, n))

lua_remove

[-1, +0, –]

void lua_remove (lua_State *L, int index);

删除给定有效索引处的元素, 向下移动此指数上方的元素以填补空白。 此函数不能使用伪索引调用, 因为伪索引不是实际的堆栈位置。

lua_replace

[-1, +0, –]

void lua_replace (lua_State *L, int index);

将顶部元素移动到给定的有效索引中 无需移动任何元素 (因此替换给定索引处的值), 然后弹出顶部元素。

lua_resetthread

[-0, +?, –]

int lua_resetthread (lua_State *L);

此函数已弃用; 它相当于与存在lua_closethread。fromNULL

lua_resume

[-?, +?, –]

int lua_resume (lua_State *L, lua_State *from, int nargs,
                          int *nresults);

在给定线程中启动和恢复协程。L

要启动协程, 你推送主函数加上任何参数 到线程的空堆栈上。 然后你打电话给lua_resume, 是参数的数量。 当协程挂起或完成其执行时,此调用将返回。 当它返回时,被更新和 堆栈顶部包含 传递给 lua_yield 的值或由 Body 函数返回的值。如果协程生成,LUA_OK协程完成执行,则返回LUA_YIELD lua_resume 没有错误, 或错误情况下的错误代码(参见 §4.4.1)。 如果出现错误, 错误对象位于堆栈的顶部。nargs*nresults*nresults

要恢复协程, 从其堆栈中删除生成的值, 推送要作为 中的结果传递的值,以 然后拨打lua_resume。*nresultsyield

该参数表示正在恢复的协程。 如果没有这样的协程, 此参数可以是 。fromLNULL

lua_rotate

[-0, +0, –]

void lua_rotate (lua_State *L, int idx, int n);

在有效索引和堆栈顶部之间旋转堆栈元素。 元素沿顶部方向旋转位置, 对于积极的, 或底部方向的位置, 对于负数. 的绝对值不得大于大小 正在旋转的切片。 此函数不能使用伪索引调用, 因为伪索引不是实际的堆栈位置。idxnn-nnn

lua_setallocf

[-0, +0, –]

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);

将给定状态的分配器功能更改为用户数据。fud

lua_setfield

[-1, +0, e]

void lua_setfield (lua_State *L, int index, const char *k);

等效于 , 给定索引处的值在哪里 并且是堆栈顶部的值。t[k] = vtv

此函数从堆栈中弹出值。 与 Lua 一样,此函数可能会触发元方法 对于“新索引”事件(参见 §2.4)。

lua_setglobal

[-1, +0, e]

void lua_setglobal (lua_State *L, const char *name);

从堆栈中弹出一个值,然后 将其设置为全局 的新值。name

lua_seti

[-1, +0, e]

void lua_seti (lua_State *L, int index, lua_Integer n);

等效于 , 给定索引处的值在哪里 并且是堆栈顶部的值。t[n] = vtv

此函数从堆栈中弹出值。 与 Lua 一样,此函数可能会触发元方法 对于“新索引”事件(参见 §2.4)。

lua_setiuservalue

[-1, +0, –]

int lua_setiuservalue (lua_State *L, int index, int n);

从堆栈中弹出一个值并将其设置为 与 关联的新第 -th 个用户值 给定索引的完整用户数据。 如果用户数据没有该值,则返回 0。n

lua_setmetatable

[-1, +0, –]

int lua_setmetatable (lua_State *L, int index);

从堆栈中弹出一个表或 nil,然后 将该值设置为给定索引处的值的新元表。 (nil 表示没有元表。

(由于历史原因,此函数返回一个 , 现在始终为 1.)int

lua_settable

[-2, +0, e]

void lua_settable (lua_State *L, int index);

等效于 , 其中 是给定索引处的值,是堆栈顶部的值, 并且是刚好低于顶部的值。t[k] = vtvk

此函数从堆栈中弹出键和值。 与 Lua 一样,此函数可能会触发元方法 对于“新索引”事件(参见 §2.4)。

lua_settop

[-?, +?, e]

void lua_settop (lua_State *L, int index);

接受任何索引,或 0, 并将堆栈顶部设置为此索引。 如果新顶部大于旧顶部, 然后用 nil 填充新元素。 如果为 0,则删除所有堆栈元素。index

此函数可以在删除索引时运行任意代码 从堆栈中标记为待关闭。

lua_setwarnf

[-0, +0, –]

void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud);

设置 Lua 发出警告时使用的警告函数 (见lua_WarnFunction)。 参数将传递给的值设置为 警告功能。udud

lua_State

typedef struct lua_State lua_State;

间接指向线程的不透明结构 (通过线程)到 Lua 解释器的整个状态。 Lua 库是完全可重入的: 它没有全局变量。 有关状态的所有信息都可以通过此结构访问。

指向此结构的指针必须作为第一个参数传递给 库中的每个函数,除了lua_newstate, 从头开始创建 Lua 状态。

lua_status

[-0, +0, –]

int lua_status (lua_State *L);

返回线程的状态。L

对于普通线程,状态可以LUA_OK, 如果线程完成执行,则为错误代码 有错误的lua_resume, 或LUA_YIELD线程是否挂起。

只能在状态LUA_OK的线程中调用函数。 您可以使用状态LUA_OK(启动新的协程)或LUA_YIELD(恢复协程)恢复线程。

lua_stringtonumber

[-0, +1, –]

size_t lua_stringtonumber (lua_State *L, const char *s);

将零结尾的字符串转换为数字, 将该数字推入堆栈, 并返回字符串的总大小, 也就是说,它的长度加一。 转换可以产生整数或浮点数, 根据Lua的词汇惯例(见§3.1)。 字符串可以具有前导和尾随空格以及符号。 如果字符串不是有效的数字, 返回 0 并且不推送任何内容。 (请注意,结果可以用作布尔值, 如果转换成功,则为 true。s

lua_toboolean

[-0, +0, –]

int lua_toboolean (lua_State *L, int index);

将给定索引处的 Lua 值转换为 C 布尔值 值(0 或 1)。 与 Lua 中的所有测试一样,lua_toboolean 对任何 Lua 值都返回 true。 不同于; 否则返回 false。 (如果只想接受实际的布尔值, 使用 lua_isboolean 测试值的类型。

lua_tocfunction

[-0, +0, –]

lua_CFunction lua_tocfunction (lua_State *L, int index);

将给定索引处的值转换为 C 函数。 该值必须是 C 函数; 否则,返回 。NULL

lua_toclose

[-0, +0, ]

void lua_toclose (lua_State *L, int index);

将堆栈中的给定索引标记为 待关闭插槽(参见 §3.3.8)。 就像 Lua 中要闭合的变量一样, 堆栈中该插槽的值将被关闭 当它超出范围时。 在这里,在 C 函数的上下文中, 超出范围意味着运行函数返回 Lua, 或者有错误, 或者通过lua_settop或lua_pop从堆栈中移除插槽, 或者有电话要lua_closeslot。 标记为待关闭的插槽不应从堆栈中移除 通过 API 中除 lua_settop 或 lua_pop 之外的任何其他函数, 除非之前被lua_closeslot停用。

不应为索引调用此函数 等于或低于活动待关闭插槽。

请注意,无论是在出现错误还是定期退货的情况下, 到元方法运行时, C 堆栈已经展开, 以便在调用函数中声明的任何自动 C 变量 (例如,缓冲区)将超出范围。__close

lua_tointeger

[-0, +0, –]

lua_Integer lua_tointeger (lua_State *L, int index);

等效于 lua_tointegerx 等于 。isnumNULL

lua_tointegerx

[-0, +0, –]

lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);

转换给定索引处的 Lua 值 到有符号整数类型 lua_Integer。 Lua 值必须是整数, 或可转换为整数的数字或字符串(参见 §3.4.3); 否则,返回 0。lua_tointegerx

如果不是 , 它的参照物被分配了一个布尔值,该值 指示操作是否成功。isnumNULL

lua_tolstring

[-0, +0, ]

const char *lua_tolstring (lua_State *L, int index, size_t *len);

将给定索引处的 Lua 值转换为 C 字符串。 如果不是 , 它与字符串长度一起设置。 Lua 值必须是字符串或数字; 否则,该函数返回 . 如果值为数字, 然后还将堆栈中的实际值更改为字符串。 (此更改混淆了lua_next表遍历期间何时应用于键。lenNULL*lenNULLlua_tolstringlua_tolstring

lua_tolstring返回指针 到 Lua 状态中的字符串(参见 §4.1.3)。 此字符串始终具有零 ('') 在其最后一个字符之后(如 C 中), 但可以在其正文中包含其他零。\0

lua_tonumber

[-0, +0, –]

lua_Number lua_tonumber (lua_State *L, int index);

等效于等于 的lua_tonumberx 。isnumNULL

lua_tonumberx

[-0, +0, –]

lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);

转换给定索引处的 Lua 值 到 C 型lua_Number(见lua_Number)。 Lua 值必须是数字或可转换为数字的字符串 (见§3.4.3); 否则,lua_tonumberx返回 0。

如果不是 , 它的参照物被分配了一个布尔值,该值 指示操作是否成功。isnumNULL

lua_topointer

[-0, +0, –]

const void *lua_topointer (lua_State *L, int index);

将给定索引处的值转换为泛型 C 指针 ()。 该值可以是用户数据、表、线程、字符串或函数; 否则,返回 。 不同的对象会给出不同的指针。 无法将指针转换回其原始值。void*lua_topointerNULL

通常,此函数仅用于哈希和调试信息。

lua_tostring

[-0, +0, ]

const char *lua_tostring (lua_State *L, int index);

等效于 lua_tolstring 等于 。lenNULL

lua_tothread

[-0, +0, –]

lua_State *lua_tothread (lua_State *L, int index);

将给定索引处的值转换为 Lua 线程 (表示为 )。 此值必须是线程; 否则,该函数返回 .lua_State*NULL

lua_touserdata

[-0, +0, –]

void *lua_touserdata (lua_State *L, int index);

如果给定索引处的值是完整的用户数据, 返回其内存块地址。 如果值是轻用户数据, 返回其值(指针)。 否则,返回 。NULL

lua_type

[-0, +0, –]

int lua_type (lua_State *L, int index);

返回给定有效索引中值的类型, 或用于无效但可接受的索引。 lua_type返回的类型由以下常量编码 定义于 : LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, 和LUA_TLIGHTUSERDATALUA_TNONElua.h

lua_typename

[-0, +0, –]

const char *lua_typename (lua_State *L, int tp);

返回由值 编码的类型的名称, 它必须是 lua_type 返回的值之一。tp

lua_Unsigned

typedef ... lua_Unsigned;

lua_Integer的未签名版本。

lua_upvalueindex

[-0, +0, –]

int lua_upvalueindex (int i);

返回表示 -th 上行值的伪索引 运行函数(参见 §4.2)。 必须在 [1,256] 范围内。ii

lua_version

[-0, +0, –]

lua_Number lua_version (lua_State *L);

返回此内核的版本号。

lua_WarnFunction

typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);

警告函数的类型,由 Lua 调用以发出警告。 第一个参数是不透明的指针 由lua_setwarnf设置。 第二个参数是警告消息。 第三个参数是一个布尔值,它 指示消息是否 在下一次调用中继续消息。

有关警告的更多详细信息,请参阅警告。

lua_warning

[-0, +0, –]

void lua_warning (lua_State *L, const char *msg, int tocont);

发出带有给定消息的警告。 调用中带有 true 的消息应该是 继续调用此函数。tocont

有关警告的更多详细信息,请参阅警告

lua_Writer

typedef int (*lua_Writer) (lua_State *L,
                           const void* p,
                           size_t sz,
                           void* ud);

lua_dump使用的编写器函数的类型。 每当lua_dump产生另一块块时, 它叫作家, 传递要写入的缓冲区 (), 它的大小 (), 以及提供给lua_dump的参数。pszud

编写器返回错误代码: 0 表示没有错误; 任何其他值表示错误并停止lua_dump 再次打电话给作家。

lua_xmove

[-?, +?, –]

void lua_xmove (lua_State *from, lua_State *to, int n);

在具有相同状态的不同线程之间交换值。

此函数从堆栈中弹出值, 并将它们推到堆栈上.nfromto

lua_yield

[-?, +?, v]

int lua_yield (lua_State *L, int nresults);

此函数等效于lua_yieldk, 但它没有延续(见§4.5)。 因此,当线程恢复时, 它继续调用的函数 函数调用 。 为避免意外, 此函数应仅在尾部调用中调用。lua_yield

lua_yieldk

[-?, +?, v]

int lua_yieldk (lua_State *L,
                int nresults,
                lua_KContext ctx,
                lua_KFunction k);

生成协程(线程)。

当 C 函数调用lua_yieldk时, 正在运行的协程暂停其执行, 并且启动此协程的对lua_resume的调用将返回。 参数是堆栈中的值数 这将作为结果传递给lua_resume。nresults

当协程再次恢复时, Lua 调用给定的延续函数以继续 执行产生的 C 函数(参见 §4.5)。 此继续函数接收相同的堆栈 从上一个函数, 删除结果并 替换为传递给lua_resume的参数。 此外 继续函数接收传递给lua_yieldk的值。knctx

通常,此函数不返回; 当协程最终恢复时, 它继续执行继续函数。 但是,有一个特例, 这是调用此函数时 从行内或计数钩内(参见§4.7)。 在这种情况下,应调用而不带延续 (可能以lua_yield的形式)并且没有结果, 并且钩子应该在调用后立即返回。 Lua会屈服,并且, 当协程再次恢复时, 它将继续正常执行 触发钩子的 (Lua) 函数。lua_yieldk

如果从线程调用此函数,则可能会引发错误 带有没有继续函数的挂起 C 调用 (所谓的C-call边界), 或者从未在简历中运行的线程调用 (通常是主线程)。

4.7 – 调试接口

Lua 没有内置的调试工具。 相反,它提供了一个特殊的界面。 通过函数和钩子。 此接口允许构建不同的 各种调试器、探查器和其他工具 需要口译员的“内部信息”。

lua_Debug

typedef struct lua_Debug {
  int event;
  const char *name;           /* (n) */
  const char *namewhat;       /* (n) */
  const char *what;           /* (S) */
  const char *source;         /* (S) */
  size_t srclen;              /* (S) */
  int currentline;            /* (l) */
  int linedefined;            /* (S) */
  int lastlinedefined;        /* (S) */
  unsigned char nups;         /* (u) number of upvalues */
  unsigned char nparams;      /* (u) number of parameters */
  char isvararg;              /* (u) */
  char istailcall;            /* (t) */
  unsigned short ftransfer;   /* (r) index of first value transferred */
  unsigned short ntransfer;   /* (r) number of transferred values */
  char short_src[LUA_IDSIZE]; /* (S) */
  /* private part */
  other fields
} lua_Debug;

用于承载不同碎片的结构 有关函数或激活记录的信息。lua_getstack仅填充私人部分 此结构,供以后使用。 要用有用的信息填充lua_Debug的其他字段, 必须使用适当的参数调用lua_getinfo。 (具体来说,要获取一个字段, 您必须在字段注释的括号之间添加字母 到lua_getinfo的参数。what

lua_Debug的字段具有以下含义:

  • 源:创建函数的区块的。 如果以 '' 开头, 这意味着该函数是在文件中定义的,其中 文件名跟在“”后面。 如果以 '' 开头, 其其余内容以依赖于用户的方式描述源。 否则 该函数是在字符串中定义的,该字符串在哪里。source@@source=source
  • 斯克伦: 字符串的长度。source
  • short_src要在错误消息中使用的 的“可打印”版本。source
  • 定义函数定义的开始行号。
  • 最后定义:函数定义结束的行号。
  • what如果函数是Lua函数,如果是C函数,如果它是块的主要部分,则为字符串。"Lua""C""main"
  • 当前行:执行给定函数的当前行。 当没有可用的行信息时,设置为 -1。currentline
  • 名称:给定函数的合理名称。 因为 Lua 中的函数是一等值, 它们没有固定的名称: 有些函数可以是多个全局变量的值, 而其他的只能存储在表字段中。 该函数检查函数的运行方式 打电话来寻找合适的名字。 如果找不到名称, 则设置为 。lua_getinfonameNULL
  • 名称内容解释字段。 的值可以是 、、、、 或(空字符串), 根据函数的调用方式。 (Lua 在没有其他选项适用时使用空字符串。namenamewhat"global""local""method""field""upvalue"""
  • istailcall如果此函数调用由尾部调用调用,则为 true。 在这种情况下,此级别的调用方不在堆栈中。
  • NUPS函数的上值数。
  • n参数:函数的参数数 (C 函数始终为 0)。
  • isvararg如果函数是可变参数函数,则为 true。 (对于 C 函数始终为真)。
  • ftransfer堆栈中第一个值被“传输”的索引, 即调用中的参数或返回中的返回值。 (其他值在连续索引中。 使用此索引,可以访问和修改这些值 通过lua_getlocallua_setlocal。 此字段仅在 调用钩子,表示第一个参数, 或返回钩子,表示返回的第一个值。 (对于调用挂钩,此值始终为 1。
  • ntransfer: 要传输的值数(请参阅上一项)。 (对于 Lua 函数的调用, 此值始终等于 。)nparams

lua_gethook

[-0, +0, –]

lua_Hook lua_gethook (lua_State *L);

返回当前挂钩函数。

lua_gethookcount

[-0, +0, –]

int lua_gethookcount (lua_State *L);

返回当前挂钩计数。

lua_gethookmask

[-0, +0, –]

int lua_gethookmask (lua_State *L);

返回当前挂钩掩码。

lua_getinfo

[-(0|1), +(0|1|2), ]

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

获取有关特定函数或函数调用的信息。

若要获取有关函数调用的信息, 该参数必须是有效的激活记录,该记录是 由先前对lua_getstack或 作为钩子的参数给出(见lua_Hook)。ar

要获取有关函数的信息,请将其推送到堆栈上 并以字符 '' 开头字符串。 (在这种情况下,从堆栈顶部弹出函数。 例如,要知道函数是在哪一行定义的, 您可以编写以下代码:what>lua_getinfof

     lua_Debug ar;
     lua_getglobal(L, "f");  /* get global 'f' */
     lua_getinfo(L, ">S", &ar);
     printf("%d\n", ar.linedefined);

字符串中的每个字符选择要填充的结构的某些字段或 要在堆栈上推送的值。 (这些字符也记录在声明中 结构lua_Debug, 在每个字段后面的注释中的括号之间。whatar

  • 'f':将 在给定水平上运行;
  • l”:填写字段currentline;
  • n”:填写字段和namenamewhat;
  • r”:填写字段和ftransferntransfer;
  • S”:填写字段 、 、 和sourceshort_srclinedefinedlastlinedefinedwhat;
  • t”:填写字段istailcall;
  • 'u':填写字段 、 和nupsnparamsisvararg;
  • 'L':将索引为 函数上的行与一些关联的代码, 也就是说,可以放置断点的行。 (没有代码的行包括空行和注释。 如果此选项与选项“”一起给出, 它的表在函数之后推送。 这是可能引发内存错误的唯一选项。f

此函数返回 0 表示 中的选项无效; 即便如此,有效选项也会得到正确处理。what

lua_getlocal

[-0, +(0|1), –]

const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);

获取有关局部变量或临时值的信息 给定的激活记录或给定的功能。

在第一种情况下, 该参数必须是有效的激活记录,该记录是 由先前对lua_getstack或 作为钩子的参数给出(见lua_Hook)。 索引选择要检查的局部变量; 有关变量索引的详细信息,请参阅 debug.getLocal 和名称。arn

lua_getlocal将变量的值推送到堆栈上 并返回其名称。

在第二种情况下,必须是和函数 要检查的必须位于堆栈的顶部。 在这种情况下,只有 Lua 函数的参数可见 (因为没有关于哪些变量处于活动状态的信息) 并且没有值被推送到堆栈上。arNULL

返回(并且不推送任何内容) 当指数大于 活动局部变量的数量。NULL

lua_getstack

[-0, +0, –]

int lua_getstack (lua_State *L, int level, lua_Debug *ar);

获取有关解释器运行时堆栈的信息。

此函数填充lua_Debug结构的各个部分 在给定级别执行的函数的激活记录的标识。 级别 0 是当前运行函数, 而级别 n+1 是调用级别 n 的函数(尾部调用除外,它们不计入堆栈)。 当调用级别大于堆栈深度时,lua_getstack返回 0; 否则返回 1。

lua_getupvalue

[-0, +(0|1), –]

const char *lua_getupvalue (lua_State *L, int funcindex, int n);

获取有关 -th 上行值的信息 索引处的收盘价。 它将升值的值推到堆栈上 并返回其名称。 返回(并且不推送任何内容) 当索引大于上行值的数量时。nfuncindexNULLn

有关upvalues的更多信息,请参阅debug.getupvalue

lua_Hook

typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);

用于调试挂钩函数的类型。

每当调用钩子时,其参数都会将其字段设置为触发钩子的特定事件。 Lua 使用以下常量标识这些事件:LUA_HOOKCALLLUA_HOOKRETLUA_HOOKTAILCALLLUA_HOOKLINE、 和LUA_HOOKCOUNT。 此外,对于行事件,还会设置该字段。 要获取 中任何其他字段的值,请执行以下操作: 钩子必须调用lua_getinfo。areventcurrentlinear

对于呼叫事件,可以是 , 正常值,或 ,表示尾部调用; 在这种情况下,将没有相应的返回事件。eventLUA_HOOKCALLLUA_HOOKTAILCALL

当 Lua 运行钩子时,它会禁用对钩子的其他调用。 因此,如果钩子回调 Lua 来执行函数或块, 此执行无需调用任何钩子即可执行。

钩子函数不能有延续, 也就是说,他们不能使用非 null 调用lua_yieldk、lua_pcallk或lua_callk。k

钩子函数可以在以下条件下产生: 只有计数和行事件才能产生; 要产生,钩子函数必须完成其执行 调用等于零的lua_yield (即,没有值)。nresults

lua_sethook

[-0, +0, –]

void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

设置调试挂钩函数。

参数是钩子函数。 指定将在哪些事件上调用挂钩: 它由常数 LUA_MASKCALLLUA_MASKRET、LUA_MASKLINE、 和LUA_MASKCOUNT。 仅当掩码时才有意义 包括。 对于每个事件,调用钩子如下所述:fmaskcountLUA_MASKCOUNT

  • 调用钩子:在解释器调用函数时调用。 钩子是在 Lua 进入新函数后调用的。
  • return hook: 在解释器从函数返回时调用。 钩子是在 Lua 离开函数之前调用的。
  • 行钩:在解释器即将调用 开始执行一行新的代码, 或者当它跳回到代码中时(甚至跳回到同一行)。 此事件仅在 Lua 执行 Lua 函数时发生。
  • count hook: 在解释器执行每条指令后调用。 此事件仅在 Lua 执行 Lua 函数时发生。count

通过设置为零来禁用钩子。mask

lua_setlocal

[-(0|1), +0, –]

const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);

设置给定激活记录的局部变量的值。 它在堆栈顶部分配值 并返回其名称。 它还会从堆栈中弹出值。

返回(并且不弹出任何内容) 当指数大于 活动局部变量的数量。NULL

参数和函数lua_getlocal中一样。arn

lua_setupvalue

[-(0|1), +0, –]

const char *lua_setupvalue (lua_State *L, int funcindex, int n);

设置闭包的上值。 它在堆栈顶部分配值 并返回其名称。 它还会从堆栈中弹出值。

返回(并且不弹出任何内容) 当索引大于上行值的数量时。NULLn

参数和如 函数lua_getupvalue。funcindexn

lua_upvalueid

[-0, +0, –]

void *lua_upvalueid (lua_State *L, int funcindex, int n);

返回从索引处的闭包编号的上值的唯一标识符。nfuncindex

这些唯一标识符允许程序检查是否不同 闭包共享升值。 共享升值的 Lua 闭包 (即,访问相同的外部局部变量) 将为这些升值指数返回相同的 ID。

参数和如 函数lua_getupvalue, 但不能大于上值的数量。funcindexnn

lua_upvaluejoin

[-0, +0, –]

void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
                                    int funcindex2, int n2);

使 Lua 闭包在索引处的第 -th 升值是指索引处 Lua 闭包的第 -th 上值。n1funcindex1n2funcindex2

5 – 辅助图书馆

辅助库提供多种方便的功能 将 C 与 Lua 接口。 虽然基本 API 为所有 C和Lua之间的相互作用, 辅助库为某些提供更高级别的功能 常见任务。

辅助库中的所有函数和类型 在头文件中定义,并且 有一个前缀 .lauxlib.hluaL_

辅助库中的所有函数都构建在 在基本 API 之上, 因此,它们不提供该 API 无法完成的任何操作。 然而,使用辅助库可确保 提高代码的一致性。

辅助库中的几个函数在内部使用一些 额外的堆栈插槽。 当辅助库中的函数使用少于五个插槽时, 它不检查堆栈大小; 它只是假设有足够的插槽。

辅助库中的几个函数用于 检查 C 函数参数。 因为错误消息已针对参数进行格式化 (例如,“”), 不应将这些函数用于其他堆栈值。bad argument #1

如果不满足检查,调用的函数总是引发错误。luaL_check*

5.1 – 函数和类型

在这里,我们列出了辅助库中的所有函数和类型 按字母顺序排列。

luaL_addchar

[-?, +?, ]

void luaL_addchar (luaL_Buffer *B, char c);

将字节添加到缓冲区(请参阅luaL_Buffer)。cB

luaL_addgsub

[-?, +?, ]

const void luaL_addgsub (luaL_Buffer *B, const char *s,
                         const char *p, const char *r);

将字符串的副本添加到缓冲区(请参阅luaL_Buffer), 将字符串的任何匹配项替换为字符串 。sBpr

luaL_addlstring

[-?, +?, ]

void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);

将长度指向的字符串添加到 缓冲区(请参阅luaL_Buffer)。 字符串可以包含嵌入的零。slB

luaL_addsize

[-?, +?, –]

void luaL_addsize (luaL_Buffer *B, size_t n);

将先前复制到 缓冲区(见luaL_prepbuffer)。Bn

luaL_addstring

[-?, +?, ]

void luaL_addstring (luaL_Buffer *B, const char *s);

将指向 的以零结尾的字符串添加到缓冲区(请参阅luaL_Buffer)。sB

luaL_addvalue

[-?, +?, ]

void luaL_addvalue (luaL_Buffer *B);

将堆栈顶部的值相加 到缓冲区(请参阅luaL_Buffer)。 弹出值。B

这是字符串缓冲区上唯一可以(并且必须)的函数 使用堆栈上的额外元素调用, 这是要添加到缓冲区的值。

luaL_argcheck

[-0, +0, v]

void luaL_argcheck (lua_State *L,
                    int cond,
                    int arg,
                    const char *extramsg);

检查是否为真。 如果不是,则使用标准消息引发错误(请参阅luaL_argerror)。cond

luaL_argerror

[-0, +0, v]

int luaL_argerror (lua_State *L, int arg, const char *extramsg);

引发错误,报告调用它的 C 函数的参数问题, 使用标准消息 其中包括作为评论:argextramsg

     bad argument #arg to 'funcname' (extramsg)

此函数永远不会返回。

luaL_argexpected

[-0, +0, v]

void luaL_argexpected (lua_State *L,
                       int cond,
                       int arg,
                       const char *tname);

检查是否为真。 如果不是,则使用标准消息引发有关参数类型的错误(请参阅luaL_typeerror)。condarg

luaL_Buffer

typedef struct luaL_Buffer luaL_Buffer;

字符串缓冲区的类型。

字符串缓冲区允许 C 代码逐段构建 Lua 字符串。 其使用模式如下:

  • 首先声明一个类型 luaL_Buffer 的变量。b
  • 然后用调用初始化它。luaL_buffinit(L, &b)
  • 然后将字符串片段添加到缓冲区中,调用任何 函数。luaL_add*
  • 最后通过调用 完成。 此调用将最后一个字符串保留在堆栈顶部。luaL_pushresult(&b)

如果您事先知道结果字符串的最大大小, 您可以像这样使用缓冲区:

  • 首先声明一个类型 luaL_Buffer 的变量。b
  • 然后初始化它并预分配一个空间 大小与调用 .szluaL_buffinitsize(L, &b, sz)
  • 然后将字符串生成到该空间中。
  • 最后通过调用 , 其中 是结果字符串的总大小 复制到该空间(可能小于或 等于预分配的大小)。luaL_pushresultsize(&b, sz)sz

在其正常运行期间, 字符串缓冲区使用可变数量的堆栈槽。 因此,在使用缓冲区时,您不能假设您知道在哪里 堆栈的顶部是。 您可以在连续调用缓冲区操作之间使用该堆栈 只要这种使用是平衡的; 那是 调用缓冲区操作时, 堆栈处于同一级别 这是在上一次缓冲操作之后立即进行的。 (此规则的唯一例外是luaL_addvalue。 打电话luaL_pushresult后, 堆栈返回到缓冲区初始化时的水平, 加上其顶部的最后一个字符串。

luaL_buffaddr

[-0, +0, –]

char *luaL_buffaddr (luaL_Buffer *B);

返回缓冲区当前内容的地址(请参见luaL_Buffer)。 请注意,对缓冲区的任何添加都可能使此地址无效。B

luaL_buffinit

[-0, +?, –]

void luaL_buffinit (lua_State *L, luaL_Buffer *B);

初始化缓冲区(请参见luaL_Buffer)。 此函数不分配任何空间; 缓冲区必须声明为变量。B

luaL_bufflen

[-0, +0, –]

size_t luaL_bufflen (luaL_Buffer *B);

返回缓冲区当前内容的长度(请参阅luaL_Buffer)。B

luaL_buffinitsize

[-?, +?, ]

char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);

相当于序列luaL_buffinit,luaL_prepbuffsize。

luaL_buffsub

[-?, +?, –]

void luaL_buffsub (luaL_Buffer *B, int n);

从缓冲区中删除字节(请参阅luaL_Buffer)。 缓冲区必须至少具有这么多字节。nB

luaL_callmeta

[-0, +(0|1), e]

int luaL_callmeta (lua_State *L, int obj, const char *e);

调用元方法。

如果索引处的对象有一个元表,并且这个 元表有一个字段, 此函数调用此字段,将对象作为其唯一参数传递。 在这种情况下,此函数返回 true 并推送到 堆叠调用返回的值。 如果没有元表或没有元方法, 此函数返回 false,而不在堆栈上推送任何值。obje

luaL_checkany

[-0, +0, v]

void luaL_checkany (lua_State *L, int arg);

检查函数是否有参数 任何类型(包括)的位置。arg

luaL_checkinteger

[-0, +0, v]

lua_Integer luaL_checkinteger (lua_State *L, int arg);

检查函数参数是否为整数 (或可以转换为整数) 并返回此整数。arg

luaL_checklstring

[-0, +0, v]

const char *luaL_checklstring (lua_State *L, int arg, size_t *l);

检查函数参数是否为字符串 并返回此字符串; 如果不是填充其引用 与字符串的长度。arglNULL

此函数使用 lua_tolstring 来获取其结果, 因此,该函数的所有转换和警告都适用于此处。

luaL_checknumber

[-0, +0, v]

lua_Number luaL_checknumber (lua_State *L, int arg);

检查函数参数是否为数字 并返回此转换为 .arglua_Number

luaL_checkoption

[-0, +0, v]

int luaL_checkoption (lua_State *L,
                      int arg,
                      const char *def,
                      const char *const lst[]);

检查函数参数是否为字符串和 在数组中搜索此字符串(必须以 NULL 结尾)。 返回找到字符串的数组中的索引。 如果参数不是字符串或 如果找不到字符串。arglst

如果不是 , 该函数在以下情况下用作默认值 没有参数或当此参数为时。defNULLdefarg

这是将字符串映射到 C 枚举的有用函数。 (Lua 库中的通常约定是 使用字符串而不是数字来选择选项。

luaL_checkstack

[-0, +0, v]

void luaL_checkstack (lua_State *L, int sz, const char *msg);

将堆栈大小增加到元素, 如果堆栈无法增长到该大小,则会引发错误。 是进入错误消息的附加文本 (或无附加文本)。top + szmsgNULL

luaL_checkstring

[-0, +0, v]

const char *luaL_checkstring (lua_State *L, int arg);

检查函数参数是否为字符串 并返回此字符串。arg

此函数使用 lua_tolstring 来获取其结果, 因此,该函数的所有转换和警告都适用于此处。

luaL_checktype

[-0, +0, v]

void luaL_checktype (lua_State *L, int arg, int t);

检查函数参数是否具有类型 。 有关 的类型编码,请参见lua_type。argtt

luaL_checkudata

[-0, +0, v]

void *luaL_checkudata (lua_State *L, int arg, const char *tname);

检查函数参数是否为用户数据 类型(见luaL_newmetatable)和 返回用户数据的内存块地址(请参阅lua_touserdata)。argtname

luaL_checkversion

[-0, +0, v]

void luaL_checkversion (lua_State *L);

检查进行调用的代码和 Lua 库是否被调用 使用相同的 Lua 版本和相同的数字类型。

luaL_dofile

[-0, +?, m]

int luaL_dofile (lua_State *L, const char *filename);

加载并运行给定的文件。 它定义为以下宏:

     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))

如果没有错误,则返回 0 (LUA_OK), 或 1 如果出现错误。

luaL_dostring

[-0, +?, –]

int luaL_dostring (lua_State *L, const char *str);

加载并运行给定的字符串。 它定义为以下宏:

     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))

如果没有错误,则返回 0 (LUA_OK), 或 1 如果出现错误。

luaL_error

[-0, +0, v]

int luaL_error (lua_State *L, const char *fmt, ...);

引发错误。 错误消息格式由加上任何额外的参数给出, 遵循相同的lua_pushfstring规则。 它还会在消息的开头添加文件名和 发生错误的行号, 如果此信息可用。fmt

此函数永远不会返回, 但在 C 函数中使用它是一个成语 如。return luaL_error(args)

luaL_execresult

[-0, +3, ]

int luaL_execresult (lua_State *L, int stat);

此函数生成 的返回值 标准库中与过程相关的函数 (os.execute 和 io.close)。

luaL_fileresult

[-0, +(1|3), ]

int luaL_fileresult (lua_State *L, int stat, const char *fname);

此函数生成 的返回值 标准库中与文件相关的函数 (io.open,os.rename,file:seek等)。

luaL_getmetafield

[-0, +(0|1), ]

int luaL_getmetafield (lua_State *L, int obj, const char *e);

将元表中的字段推送到堆栈上 索引处的对象,并返回推送值的类型。 如果对象没有元表, 或者如果元表没有此字段, 什么都不推,然后返回.eobjLUA_TNIL

luaL_getmetatable

[-0, +1, ]

int luaL_getmetatable (lua_State *L, const char *tname);

将与注册表中的名称关联的元表推送到堆栈上(请参阅luaL_newmetatable), 如果没有与该名称关联的元表,则为 nil。 返回推送值的类型。tname

luaL_getsubtable

[-0, +1, e]

int luaL_getsubtable (lua_State *L, int idx, const char *fname);

确保值 , 索引处的值在哪里, 是一个表, 并将该表推到堆栈上。 如果它在那里找到前一个表,则返回 true 如果它创建一个新表,则为 false。t[fname]tidx

luaL_gsub

[-0, +1, ]

const char *luaL_gsub (lua_State *L,
                       const char *s,
                       const char *p,
                       const char *r);

创建字符串的副本 , 将字符串的任何匹配项替换为字符串 。 将生成的字符串推送到堆栈上并返回它。spr

luaL_len

[-0, +0, e]

lua_Integer luaL_len (lua_State *L, int index);

返回给定索引处值的“长度” 作为一个数字; 它等效于 Lua 中的 '' 运算符(参见 §3.4.7)。 如果操作的结果不是整数,则引发错误。 (这种情况只能通过元方法发生。#

luaL_loadbuffer

[-0, +1, –]

int luaL_loadbuffer (lua_State *L,
                     const char *buff,
                     size_t sz,
                     const char *name);

等效于 luaL_loadbufferx 等于 。modeNULL

luaL_loadbufferx

[-0, +1, –]

int luaL_loadbufferx (lua_State *L,
                      const char *buff,
                      size_t sz,
                      const char *name,
                      const char *mode);

将缓冲区加载为 Lua 块。 此函数使用 lua_load 在 缓冲区指向大小。buffsz

此函数返回与lua_load相同的结果。 是块名称, 用于调试信息和错误消息。 该字符串的工作方式与函数 lua_load 中相同。namemode

luaL_loadfile

[-0, +1, ]

int luaL_loadfile (lua_State *L, const char *filename);

等效于 luaL_loadfilex 等于 。modeNULL

luaL_loadfilex

[-0, +1, ]

int luaL_loadfilex (lua_State *L, const char *filename,
                                            const char *mode);

将文件加载为 Lua 块。 此函数使用 lua_load 加载文件中的块 叫。 如果是 , 然后它从标准输入加载。 如果文件中的第一行以 .filenamefilenameNULL#

该字符串的工作方式与函数 lua_load 中相同。mode

此函数返回的结果与文件相关错误的lua_load或LUA_ERRFILE相同。

lua_load,此函数仅加载块; 它不运行它。

luaL_loadstring

[-0, +1, –]

int luaL_loadstring (lua_State *L, const char *s);

将字符串加载为 Lua 块。 此函数使用 lua_load 将块加载到 以零结尾的字符串 。s

此函数返回与lua_load相同的结果。

同样lua_load,此函数仅加载块; 它不运行它。

luaL_newlib

[-0, +1, ]

void luaL_newlib (lua_State *L, const luaL_Reg l[]);

创建一个新表并在那里注册 列表中的函数 。l

它实现为以下宏:

     (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))

数组必须是实际数组, 不是指向它的指针。l

luaL_newlibtable

[-0, +1, ]

void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);

创建大小优化的新表 将所有条目存储在数组中(但实际上并不存储它们)。 它旨在与luaL_setfuncs一起使用(见luaL_newlib)。l

它是作为宏实现的。 数组必须是实际数组, 不是指向它的指针。l

luaL_newmetatable

[-0, +1, ]

int luaL_newmetatable (lua_State *L, const char *tname);

如果注册表已经有密钥 , 返回 0。 否则 创建一个新表以用作用户数据的元表, 将这对添加到此新表中, 将这对添加到注册表中, 并返回 1。tname__name = tname[tname] = new table

在这两种情况下, 该函数将关联的最终值推送到堆栈上 在注册表中。tname

luaL_newstate

[-0, +0, –]

lua_State *luaL_newstate (void);

创建新的 Lua 状态。 它lua_newstate用 基于 ISO C 分配函数的分配器 然后设置警告功能和紧急功能(参见§4.4) 将消息打印到标准错误输出。

返回新状态, 或者如果存在内存分配错误。NULL

luaL_openlibs

[-0, +0, e]

void luaL_openlibs (lua_State *L);

将所有标准 Lua 库打开到给定状态。

luaL_opt

[-0, +0, –]

T luaL_opt (L, func, arg, dflt);

此宏定义如下:

     (lua_isnoneornil(L,(arg)) ? (dflt) : func(L,(arg)))

换句话说,如果论点为零或不存在, 宏结果为默认值 . 否则,它会导致调用状态和参数索引的结果为 参数。 请注意,它仅在需要时计算表达式。argdfltfuncLargdflt

luaL_optinteger

[-0, +0, v]

lua_Integer luaL_optinteger (lua_State *L,
                             int arg,
                             lua_Integer d);

如果函数参数是整数 (或可转换为整数), 返回此整数。 如果此参数不存在或为, 返回。 否则,将引发错误。argd

luaL_optlstring

[-0, +0, v]

const char *luaL_optlstring (lua_State *L,
                             int arg,
                             const char *d,
                             size_t *l);

如果函数参数是字符串, 返回此字符串。 如果此参数不存在或为, 返回。 否则,将引发错误。argd

如果不是 , 用结果的长度填充其参照项。 如果结果是(仅在返回和时可能),则 其长度被视为零。lNULLNULLdd == NULL

此函数使用 lua_tolstring 来获取其结果, 因此,该函数的所有转换和警告都适用于此处。

luaL_optnumber

[-0, +0, v]

lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);

If the function argument is a number, returns this number as a . If this argument is absent or is nil, returns . Otherwise, raises an error. arglua_Numberd

luaL_optstring

[-0, +0, v]

const char *luaL_optstring (lua_State *L,
                            int arg,
                            const char *d);

If the function argument is a string, returns this string. If this argument is absent or is nil, returns . Otherwise, raises an error. argd

luaL_prepbuffer

[-?, +?, m]

char *luaL_prepbuffer (luaL_Buffer *B);

Equivalent to luaL_prepbuffsize with the predefined size LUAL_BUFFERSIZE.

luaL_prepbuffsize

[-?, +?, m]

char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);

Returns an address to a space of size where you can copy a string to be added to buffer (see luaL_Buffer). After copying the string into this space you must call luaL_addsize with the size of the string to actually add it to the buffer. szB

luaL_pushfail

[-0, +1, –]

void luaL_pushfail (lua_State *L);

Pushes the fail value onto the stack (see §6).

luaL_pushresult

[-?, +1, m]

void luaL_pushresult (luaL_Buffer *B);

Finishes the use of buffer leaving the final string on the top of the stack. B

luaL_pushresultsize

[-?, +1, m]

void luaL_pushresultsize (luaL_Buffer *B, size_t sz);

Equivalent to the sequence luaL_addsize, luaL_pushresult.

luaL_ref

[-1, +0, m]

int luaL_ref (lua_State *L, int t);

Creates and returns a reference, in the table at index , for the object on the top of the stack (and pops the object). t

A reference is a unique integer key. As long as you do not manually add integer keys into the table , luaL_ref ensures the uniqueness of the key it returns. You can retrieve an object referred by the reference by calling . The function luaL_unref frees a reference. trlua_rawgeti(L, t, r)

If the object on the top of the stack is nil, luaL_ref returns the constant LUA_REFNIL. The constant LUA_NOREF is guaranteed to be different from any reference returned by luaL_ref.

luaL_Reg

typedef struct luaL_Reg {
  const char *name;
  lua_CFunction func;
} luaL_Reg;

Type for arrays of functions to be registered by luaL_setfuncs. is the function name and is a pointer to the function. Any array of luaL_Reg must end with a sentinel entry in which both and are . namefuncnamefuncNULL

luaL_requiref

[-0, +1, e]

void luaL_requiref (lua_State *L, const char *modname,
                    lua_CFunction openf, int glb);

If is not true, calls the function with the string as an argument and sets the call result to , as if that function has been called through require. package.loaded[modname]openfmodnamepackage.loaded[modname]

If is true, also stores the module into the global . glbmodname

Leaves a copy of the module on the stack.

luaL_setfuncs

[-nup, +0, m]

void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);

Registers all functions in the array (see luaL_Reg) into the table on the top of the stack (below optional upvalues, see next). l

When is not zero, all functions are created with upvalues, initialized with copies of the values previously pushed on the stack on top of the library table. These values are popped from the stack after the registration. nupnupnup

A function with a value represents a placeholder, which is filled with falseNULL

luaL_setmetatable

[-0, +0, –]

void luaL_setmetatable (lua_State *L, const char *tname);

Sets the metatable of the object on the top of the stack as the metatable associated with name in the registry (see luaL_newmetatable). tname

luaL_Stream

typedef struct luaL_Stream {
  FILE *f;
  lua_CFunction closef;
} luaL_Stream;

The standard representation for file handles used by the standard I/O library.

A file handle is implemented as a full userdata, with a metatable called (where is a macro with the actual metatable's name). The metatable is created by the I/O library (see luaL_newmetatable). LUA_FILEHANDLELUA_FILEHANDLE

This userdata must start with the structure ; it can contain other data after this initial structure. The field points to the corresponding C stream (or it can be to indicate an incompletely created handle). The field points to a Lua function that will be called to close the stream when the handle is closed or collected; this function receives the file handle as its sole argument and must return either a true value, in case of success, or a false value plus an error message, in case of error. Once Lua calls this field, it changes the field value to to signal that the handle is closed. luaL_StreamfNULLclosefNULL

luaL_testudata

[-0, +0, m]

void *luaL_testudata (lua_State *L, int arg, const char *tname);

This function works like luaL_checkudata, except that, when the test fails, it returns instead of raising an error. NULL

luaL_tolstring

[-0, +1, e]

const char *luaL_tolstring (lua_State *L, int idx, size_t *len);

Converts any Lua value at the given index to a C string in a reasonable format. The resulting string is pushed onto the stack and also returned by the function (see §4.1.3). If is not , the function also sets with the string length. lenNULL*len

If the value has a metatable with a field, then calls the corresponding metamethod with the value as argument, and uses the result of the call as its result. __tostringluaL_tolstring

luaL_traceback

[-0, +1, m]

void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                     int level);

创建并推送堆栈的回溯。 如果不是,则附加 在回溯的开头。 该参数指示在哪个级别 以启动回溯。L1msgNULLlevel

luaL_typeerror

[-0, +0, v]

int luaL_typeerror (lua_State *L, int arg, const char *tname);

为调用它的 C 函数的参数引发类型错误, 使用标准消息; 是预期类型的“名称”。 此函数永远不会返回。argtname

luaL_typename

[-0, +0, –]

const char *luaL_typename (lua_State *L, int index);

返回给定索引处的值类型的名称。

luaL_unref

[-0, +0, –]

void luaL_unref (lua_State *L, int t, int ref);

从索引处的表中释放引用(请参见luaL_ref)。 该条目将从表中删除, 以便可以收集引用的对象。 该引用也会被释放出来,以便再次使用。reftref

如果是LUA_NOREF或LUA_REFNIL,luaL_unref什么都不做。ref

luaL_where

[-0, +1, ]

void luaL_where (lua_State *L, int lvl);

将标识当前位置的字符串推送到堆栈上 调用堆栈中级别的控件。 通常,此字符串具有以下格式:lvl

     chunkname:currentline:

级别 0 是运行函数, 级别 1 是调用运行函数的函数, 等。

此函数用于为错误消息构建前缀。

6 – 标准库

标准 Lua 库提供有用的函数 通过 C API 在 C 中实现。 其中一些函数为语言提供基本服务 (例如,类型和获取元表); 其他提供对外部服务(例如 I/O)的访问; 其他可以在Lua本身中实现, 但出于不同的原因 应该在C中实现(例如,table.sort)。

所有库都是通过官方 C API 实现的 并作为单独的 C 模块提供。 除非另有说明, 这些库函数不调整其参数数 到其预期参数。 例如,记录为不应在没有参数的情况下调用函数。foo(arg)

表示法失败表示假值表示 某种失败。 (目前,失败等于, 但这在未来的版本中可能会改变。 建议始终测试这些函数是否成功 用 代替 。。(not status)(status == nil)

目前,Lua 有以下标准库:

  • 基本库 (§6.1);
  • 协程库 (§6.2);
  • 软件包库 (§6.3);
  • 字符串操作 (§6.4);
  • 基本 UTF-8 支持 (§6.5);
  • 表操作 (§6.6);
  • 数学函数(§6.7)(正弦、对数等);
  • 输入和输出(§6.8);
  • 操作系统设施(§6.9);
  • 调试工具 (§6.10)。

除了基本库和包库, 每个库都将其所有功能作为全局表的字段提供 或作为其对象的方法。

要访问这些库, C 主机程序应调用 luaL_openlibs 函数, 这将打开所有标准库。 或者 宿主程序可以使用luaL_requiref单独打开它们,以调用luaopen_base(对于基本库)、luaopen_package(对于包库)、luaopen_coroutine(对于协程库)、luaopen_string(对于字符串库)、luaopen_utf8(对于 UTF-8 库)、luaopen_table(对于表库)luaopen_ 数学(用于数学库)、luaopen_io(用于 I/O 库)、luaopen_os(用于操作系统库)、 和luaopen_debug(用于调试库)。 这些函数在 lualib.h 中声明。

6.1 – 基本功能

基本库为 Lua 提供核心功能。 如果未在应用程序中包含此库, 您应该仔细检查是否需要提供 其部分设施的实施。

assert (v [, message])

在以下情况下引发错误 其参数的值为假(即 nil 或 false); 否则,返回其所有参数。 在错误的情况下,是错误对象; 当不存在时,默认为”vmessageassertion failed!"

collectgarbage ([opt [, arg]])

此函数是垃圾回收器的通用接口。 它根据其第一个参数执行不同的功能:opt

  • 收集”: 执行完整的垃圾收集周期。 这是默认选项。
  • 停止”: 停止垃圾回收器的自动执行。 收集器仅在显式调用时运行, 直到调用重新启动它。
  • 重新启动”: 重新启动垃圾回收器的自动执行。
  • 计数”: 返回 Lua 使用的总内存(以 KB 为单位)。 该值有一个小数部分, 使其乘以 1024 给出 Lua 使用的确切字节数。
  • 步骤”: 执行垃圾回收步骤。 步骤“大小”由 控制。 如果值为零, 收集器将执行一个基本(不可分割)步骤。 对于非零值, 收集器将像该内存量一样执行 (以千字节为单位)由Lua分配。 如果步骤完成了收集周期,则返回 truearg
  • 正在运行”: 返回一个布尔值,该值指示收集器是否正在运行 (即,未停止)。
  • 增量”: 将收集器模式更改为增量模式。 此选项后可以跟三个数字: 垃圾收集者停顿了一下, 阶跃乘数, 和步长(参见 §2.5.1)。 零表示不更改该值。
  • 世代”: 将收集器模式更改为分代模式。 此选项后可以跟两个数字: 垃圾收集器次要乘数 和主要乘数(见§2.5.2)。 零表示不更改该值。

有关垃圾回收的更多详细信息,请参阅 §2.5 以及其中一些选项。

此函数不应由终结器调用。

dofile ([filename])

打开命名文件并将其内容作为 Lua 块执行。 在没有参数的情况下调用时,执行标准输入 () 的内容。 返回区块返回的所有值。 如果出现错误,传播错误 到其调用方。 (即,不在保护模式下运行。dofilestdindofiledofile

error (message [, level])

引发错误(参见 §2.3)作为错误对象。 此函数永远不会返回。message

通常,添加一些有关错误位置的信息 在消息的开头,如果消息是字符串。 该参数指定如何获取错误位置。 对于级别 1(默认值),错误位置是调用函数的位置。 级别 2 将错误指向函数的位置 那个叫叫;等等。 传递级别 0 可避免添加错误位置信息 到消息。errorlevelerrorerror

_G

一个全局变量(不是函数),它 拥有全球环境(见§2.2)。 Lua 本身不使用此变量; 更改其值不会影响任何环境, 反之亦然。

getmetatable (object)

如果没有元表,则返回 nil。 否则 如果对象的元表有一个字段, 返回关联的值。 否则,返回给定对象的元表。object__metatable

ipairs (t)

返回三个值(迭代器函数、表 和 0) 使施工t

     for i,v in ipairs(t) do body end

将迭代键值对 (), (), ..., 直到第一个不存在的索引。1,t[1]2,t[2]

load (chunk [, chunkname [, mode [, env]]])

加载一个区块。

如果是一个字符串,则块就是这个字符串。 if 是一个函数,反复调用它以获取块块。 每个调用 必须返回一个串联的字符串 与之前的结果。 返回空字符串、nil 或无值表示块的结束。chunkchunkloadchunk

如果没有语法错误,则以函数形式返回已编译的块; 否则,它将返回失败和错误消息。load

当您加载主块时, 生成的函数将始终只有一个上行值, 变量(参见 §2.2)。 然而 当您加载从函数创建的二进制块时(请参阅 string.dump), 生成的函数可以具有任意数量的上行值, 并且不能保证其首次升值将是 变量。 (非主函数甚至可能没有上升值。_ENV_ENV_ENV

无论如何,如果生成的函数有任何上升值, 其第一个上行值设置为 , 如果给定该参数, 或全球环境的价值。 其他上行值初始化为 nil。 所有升值都是新鲜的,即 它们不与任何其他功能共享。env

chunkname用作错误消息的区块名称 和调试信息(参见 §4.7)。 缺席时, 它默认为 ,如果是一个字符串, 或“”,否则。chunkchunk=(load)

字符串控制区块可以是文本还是二进制 (即预编译块)。 它可能是字符串“”(只有二进制块), “”(仅文本块), 或 “”(二进制和文本)。 默认值为 “”。modebtbtbt

加载格式错误的二进制块是安全的; 表示适当的错误。 然而 Lua 不检查二进制块内代码的一致性; 运行恶意制作的字节码可能会导致解释器崩溃。load

loadfile ([filename [, mode [, env]]])

与负载类似, 但从文件或标准输入中获取块, 如果未指定文件名。filename

next (table [, index])

允许程序遍历表的所有字段。 它的第一个参数是一个表,第二个参数是 是此表中的索引。 调用 返回表的下一个索引 及其相关值。 当使用 nil 作为其第二个参数调用时,返回一个初始索引 及其相关值。 当使用最后一个索引调用时, 或在空表中使用 nil 时返回 nil。 如果第二个参数不存在,则将其解释为 nil。 特别 您可以使用 来检查表是否为空。nextnextnextnext(t)

未指定枚举索引的顺序,即使对于数字索引也是如此。 (要按数字顺序遍历表, 使用数字 for

不应为表中不存在的字段分配任何值 在其穿越过程中。 但是,您可以修改现有字段。 特别是,您可以将现有字段设置为 nil。

pairs (t)

如果有元方法, 用 as 参数调用它并返回前三个 调用的结果。t__pairst

否则 返回三个值:下一个函数、表 和 nil, 使施工t

     for k,v in pairs(t) do body end

将迭代表的所有键值对。t

有关修改的注意事项,请参阅下面的函数 遍历期间的表。

pcall (f [, arg1, ···])

调用函数 保护模式下的给定参数。 这意味着内部的任何错误都不会传播; 而是捕获错误 并返回状态代码。 它的第一个结果是状态代码(布尔值), 如果调用成功且没有错误,则为 true。 在这种情况下,还返回调用的所有结果, 在这第一个结果之后。 如果出现任何错误,则返回 false 加上错误对象。 请注意,捕获的错误不会调用消息处理程序。ffpcallpcallpcallpcall

print (···)

接收任意数量的参数 并将其值打印到 , 将每个参数转换为字符串 遵循相同的字符串规则。stdout

该函数不适用于格式化输出, 但仅作为显示值的快速方法, 例如用于调试。 为了完全控制输出, 使用 string.format 和 io.writeprint

rawequal (v1, v2)

检查是否等于 , 而不调用元方法。 返回布尔值。v1v2__eq

rawget (table, index)

获取 的实际值 , 不使用元值。 必须是表格; 可以是任何值。table[index]__indextableindex

rawlen (v)

返回对象的长度, 必须是表或字符串, 而不调用元方法。 返回一个整数。v__len

rawset (table, index, value)

将 的实际值设置为 , 不使用元值。 必须是表,任何不同于 nil 和 NaN 的值, 和任何 Lua 值。table[index]value__newindextableindexvalue

此函数返回 。table

select (index, ···)

如果是一个数字, 返回参数编号后的所有参数; 负数从末尾开始索引(-1 是最后一个参数)。 否则,必须是字符串 , 并返回它收到的额外参数的总数。indexindexindex"#"select

setmetatable (table, metatable)

设置给定表的元表。 如果为, 删除给定表的元表。 如果原始元表有一个字段, 引发错误。metatable__metatable

此函数返回 。table

要从 Lua 代码更改其他类型的元表, 必须使用调试库 (§6.10)。

tonumber (e [, base])

当调用时 no ,尝试将其参数转换为数字。 如果参数已经是一个数字或 可转换为数字的字符串, 然后返回此数字; 否则,它将返回失败basetonumbertonumber

字符串的转换可以产生整数或浮点数, 根据Lua的词汇惯例(见§3.1)。 字符串可以具有前导和尾随空格以及符号。

使用 调用时, 那么必须是字符串才能解释为 该基数中的整数。 基数可以是介于 2 和 36 之间的任何整数(包括 10 和 10)。 在 11 以上的基数中,字母 ''(大写或小写) 表示 35,'' 表示 <>,依此类推, 其中“”代表 <>。 如果字符串在给定基数中不是有效的数字, 该函数返回失败baseeABZe

tostring (v)

接收任何类型的值,并且 将其转换为人类可读格式的字符串。

如果元表有一个字段, 然后调用相应的值 与作为参数, 并使用调用的结果作为其结果。 否则,如果元表有一个字段 使用字符串值,可以在其最终结果中使用该字符串。v__tostringtostringvv__nametostring

为了完全控制数字的转换方式, 使用字符串格式

type (v)

返回其唯一参数的类型,编码为字符串。 此函数的可能结果是 “”(字符串,不是值 nil), "", "", "", "", "", "", 和“”。nilnumberstringbooleantablefunctionthreaduserdata

_VERSION

一个全局变量(不是函数),它 保存包含正在运行的 Lua 版本的字符串。 此变量的当前值为 “”。Lua 5.4

warn (msg1, ···)

Emits a warning with a message composed by the concatenation of all its arguments (which should be strings).

By convention, a one-piece message starting with '' is intended to be a control message, which is a message to the warning system itself. In particular, the standard warning function in Lua recognizes the control messages "", to stop the emission of warnings, and "", to (re)start the emission; it ignores unknown control messages. @@off@on

xpcall (f, msgh [, arg1, ···])

This function is similar to pcall, except that it sets a new message handler . msgh

6.2 – Coroutine Manipulation

This library comprises the operations to manipulate coroutines, which come inside the table coroutine. See §2.6 for a general description of coroutines.

coroutine.close (co)

Closes coroutine , that is, closes all its pending to-be-closed variables and puts the coroutine in a dead state. The given coroutine must be dead or suspended. In case of error (either the original error that stopped the coroutine or errors in closing methods), returns false plus the error object; otherwise returns trueco

coroutine.create (f)

Creates a new coroutine, with body . must be a function. Returns this new coroutine, an object with type . ff"thread"

coroutine.isyieldable ([co])

Returns true when the coroutine can yield. The default for is the running coroutine. coco

A coroutine is yieldable if it is not the main thread and it is not inside a non-yieldable C function.

coroutine.resume (co [, val1, ···])

Starts or continues the execution of coroutine . The first time you resume a coroutine, it starts running its body. The values , ... are passed as the arguments to the body function. If the coroutine has yielded, restarts it; the values , ... are passed as the results from the yield. coval1resumeval1

If the coroutine runs without any errors, returns true plus any values passed to (when the coroutine yields) or any values returned by the body function (when the coroutine terminates). If there is any error, returns false plus the error message. resumeyieldresume

coroutine.running ()

Returns the running coroutine plus a boolean, true when the running coroutine is the main one.

coroutine.status (co)

Returns the status of the coroutine , as a string: , if the coroutine is running (that is, it is the one that called ); , if the coroutine is suspended in a call to , or if it has not started running yet; if the coroutine is active but not running (that is, it has resumed another coroutine); and if the coroutine has finished its body function, or if it has stopped with an error. co"running"status"suspended"yield"normal""dead"

coroutine.wrap (f)

Creates a new coroutine, with body ; must be a function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to this function behave as the extra arguments to . The function returns the same values returned by , except the first boolean. In case of error, the function closes the coroutine and propagates the error. ffresumeresume

coroutine.yield (···)

Suspends the execution of the calling coroutine. Any arguments to are passed as extra results to . yieldresume

6.3 – Modules

The package library provides basic facilities for loading modules in Lua. It exports one function directly in the global environment: require. Everything else is exported in the table package.

require (modname)

Loads the given module. The function starts by looking into the package.loaded table to determine whether is already loaded. If it is, then returns the value stored at . (The absence of a second result in this case signals that this call did not have to load the module.) Otherwise, it tries to find a loader for the module. modnamerequirepackage.loaded[modname]

To find a loader, is guided by the table package.searchers. Each item in this table is a search function, that searches for the module in a particular way. By changing this table, we can change how looks for a module. The following explanation is based on the default configuration for package.searchers. requirerequire

First queries . If it has a value, this value (which must be a function) is the loader. Otherwise searches for a Lua loader using the path stored in package.path. If that also fails, it searches for a C loader using the path stored in package.cpath. If that also fails, it tries an all-in-one loader (see package.searchers). requirepackage.preload[modname]require

找到加载器后,使用两个参数调用加载器:和一个额外的值, 加载器数据, 也由搜索者返回。 加载器数据可以是对模块有用的任何值; 对于默认搜索者, 它指示找到加载程序的位置。 (例如,如果加载程序来自文件, 此额外值是文件路径。 如果加载程序返回任何非 nil 值,则将返回的值分配给 。 如果加载程序未返回非 nil 值,并且 尚未为 赋值 然后为此条目分配 true。 在任何情况下,返回 的最终值。 除了该值之外,还返回为第二个结果 搜索器返回的加载器数据, 这指示如何找到模块。requiremodnamerequirepackage.loaded[modname]package.loaded[modname]requirerequirepackage.loaded[modname]requirerequire

如果加载或运行模块时出现任何错误, 或者如果找不到模块的任何加载器, 然后引发错误。require

package.config

描述包的一些编译时配置的字符串。 此字符串是一系列行:

  • 第一行是目录分隔符字符串。 对于 Windows,默认值为“”,对于所有其他系统,默认值为“”。\/
  • 第二行是分隔路径中模板的字符。 默认值为“”。;
  • 第三行是标记 模板中的替换点。 默认值为“”。?
  • 第四行是一个字符串,在 Windows 中的路径中, 替换为可执行文件的目录。 默认值为“”。!
  • 第五行是忽略其后所有文本的标记 构建函数名称时。 默认值为“”。luaopen_-

package.cpath

一个字符串,其中包含 require 用于搜索 C 加载程序的路径。

Lua 以相同的方式初始化 C path package.cpath 它初始化 Lua 路径包.path, 使用环境变量LUA_CPATH_5_4, 或环境变量LUA_CPATH, 或在 中定义的默认路径。luaconf.h

package.loaded

由 require 用于控制哪个 模块已加载。 当你需要一个模块并且不为假时,require只是返回存储在那里的值。modnamepackage.loaded[modname]

此变量只是对实际表的引用; 对此变量的赋值不会更改 要求使用的表。 实际表存储在 C 注册表中(参见 §4.3), 由键LUA_LOADED_TABLE字符串索引。

package.loadlib (libname, funcname)

将主机程序与 C 库 动态链接。libname

如果为 “”, 然后它只与库链接, 使元器件库导出的符号 可用于其他动态链接的库。 否则 它在库内查找函数 并将此函数作为 C 函数返回。 所以,必须遵循lua_CFunction原型 (见lua_CFunction)。funcname*funcnamefuncname

这是一个低级函数。 它完全绕过了封装和模块系统。 与要求不同, 它不执行任何路径搜索和 不会自动添加扩展。 必须是 C 库的完整文件名, 如有必要,包括路径和扩展名。 必须是 C 库导出的确切名称 (这可能取决于所使用的 C 编译器和链接器)。libnamefuncname

ISO C 不支持此功能。 因此,它仅在某些平台上可用 (Windows, Linux, Mac OS X, Solaris, BSD, 加上支持该标准的其他 Unix 系统)。dlfcn

此功能本质上是不安全的, 因为它允许Lua在任何可读的动态中调用任何函数 系统中的库。 (Lua 调用任何假设函数的函数 具有适当的原型并尊重适当的协议 (见lua_CFunction)。 因此 调用任意动态库中的任意函数 通常会导致访问冲突。

package.path

一个字符串,其中包含 require 用于搜索 Lua 加载器的路径。

在启动时,Lua 初始化此变量 环境变量的值LUA_PATH_5_4或 环境变量LUA_PATH或 在 中定义了默认路径 , 如果未定义这些环境变量。 环境变量值中的 “” 替换为默认路径。luaconf.h;;

package.preload

用于存储特定模块加载器的表 (请参阅要求)。

此变量只是对实际表的引用; 对此变量的赋值不会更改 要求使用的表。 实际表存储在 C 注册表中(参见 §4.3), 按键LUA_PRELOAD_TABLE字符串编制索引。

package.searchers

由 require 用于控制如何查找模块的表。

此表中的每个条目都是一个搜索器函数。 查找模块时,需要按升序调用这些搜索器中的每一个, 以模块名称(给定 require 的参数)作为其 唯一的论点。 如果搜索者找到模块, 它返回另一个函数,模块加载器, 加上一个额外的值,一个加载器数据, 这将传递给该加载器,并且 作为第二个结果由 require 返回。 如果找不到模块, 它返回一个字符串来解释为什么 (如果无话可说,则为零)。

Lua 使用四个搜索器函数初始化此表。

第一个搜索器只是在package.preload表中查找加载器。

第二个搜索者寻找加载器作为 Lua 库, 使用存储在 package.path 中的路径。 搜索按照函数包中所述完成。

第三个搜索器查找加载器作为 C 库, 使用变量 package.cpath 给出的路径。 再 搜索按照函数包中所述完成。 例如 如果 C 路径是字符串

     "./?.so;./?.dll;/usr/local/?/init.so"

模块的搜索器将尝试打开文件 , , 和 ,按此顺序排列。 一旦找到 C 库, 此搜索器首先使用动态链接工具来链接 应用程序与库。 然后它尝试在库内找到一个 C 函数来 用作加载器。 此 C 函数的名称是字符串 “” 与模块名称的副本连接,其中每个点 替换为下划线。 此外,如果模块名称有连字符, 删除第一个连字符之后(并包括)的后缀。 例如,如果模块名称为 , 函数名称将为 。foo./foo.so./foo.dll/usr/local/foo/init.soluaopen_a.b.c-v2.1luaopen_a_b_c

第四个搜索器尝试使用多合一加载程序。 它在 C 路径中搜索库 给定模块的根名称。 例如,当需要 时, 它将搜索 的 C 库。 如果找到,它会在它中查找一个打开函数 子模块; 在我们的示例中,这将是 . 使用此功能,一个包可以包含多个 C 子模块 成一个单一的库, 每个子模块保持其原始的打开功能。a.b.caluaopen_a_b_c

除第一个(预加载)之外的所有搜索器都返回为额外值 找到模块的文件路径, 由 package.searchpath 返回。 第一个搜索器始终返回字符串 “”。:preload:

搜索者应该不会在Lua中提出任何错误,也没有副作用。 (它们可能在C中产生副作用, 例如,通过将应用程序与库链接。

package.searchpath (name, path [, sep [, rep]])

在给定的 .namepath

路径是一个字符串,其中包含由分号分隔的模板序列。 对于每个模板, 该功能替换每个询问标记(如果有) 在模板中带有其中所有出现的副本(默认情况下为点) 替换为(默认情况下是系统的目录分隔符), ,然后尝试打开生成的文件名。nameseprep

例如,如果路径是字符串

     "./?.lua;./?.lc;/usr/local/?/init.lua"

搜索名称将尝试按该顺序打开文件 、 和 。foo.a./foo/a.lua./foo/a.lc/usr/local/foo/a/init.lua

返回第一个文件的结果名称 在阅读模式下打开(关闭文件后), 或失败加上错误消息(如果未成功)。 (此错误消息列出了它尝试打开的所有文件名。

6.4 – 字符串操作

此库提供用于字符串操作的通用函数, 例如查找和提取子字符串以及模式匹配。 在 Lua 中为字符串编制索引时,第一个字符位于位置 1 (不是 0,如 C 中的 1)。 索引允许为负数,并被解释为向后索引, 从字符串的末尾。 因此,最后一个字符位于位置 -<>,依此类推。

字符串库在表字符串中提供其所有函数。 它还为字符串设置元表 字段指向表的位置。 因此,可以在面向对象的样式中使用字符串函数。 例如,可以写为 .__indexstringstring.byte(s,i)s:byte(i)

字符串库采用单字节字符编码。

string.byte (s [, i [, j]])

返回字符 、...、 的内部数字代码。 的默认值为 1; 的缺省值为 。 这些指数已更正 遵循与函数字符串相同的规则。s[i]s[i+1]s[j]iji

数字代码不一定可以跨平台移植。

string.char (···)

接收零个或多个整数。 返回长度等于参数数的字符串, 其中每个字符的内部数字代码相等 到其相应的参数。

数字代码不一定可以跨平台移植。

string.dump (function [, strip])

返回包含二进制表示形式的字符串 (二进制块) 给定函数, 以便稍后对此字符串的加载返回 函数的副本(但具有新的上行值)。 如果为真值, 二进制表示形式可能不包括所有调试信息 关于函数, 以节省空间。strip

具有上值的函数仅保存其上值数。 当(重新)加载时, 这些上值将收到新的实例。 (有关以下内容的详细信息,请参阅加载函数 如何初始化这些上值。 可以使用调试库进行序列化 并重新加载函数的上行值 以足以满足您的需求的方式。

string.find (s, pattern [, init [, plain]])

在字符串中查找 的第一个匹配项(请参阅 §6.4.1)。 如果找到匹配项,则返回此事件的开始和结束位置的索引; 否则,它将返回失败。 第三个可选数值参数指定 从哪里开始搜索; 其默认值为 1,可以为负数。 如果为 true,则为第四个可选参数会关闭模式匹配功能, 所以该函数执行简单的“查找子字符串”操作, 没有被认为是魔法的角色。patternsfindsinitplainpattern

如果模式具有捕获, 然后在一场成功的比赛中 捕获的值也会返回, 在两个指数之后。

string.format (formatstring, ···)

返回其可变参数数的格式化版本 按照其第一个参数中给出的描述, 它必须是字符串。 格式字符串遵循与 ISO C 函数相同的规则。 唯一的区别是不支持转换说明符和修饰符、和 并且还有一个额外的说明符. 宽度和精度(如果存在), 限制为两位数。sprintfFn*hLlq

说明符设置布尔值、nil、数字和字符串的格式 在某种程度上,结果是 Lua 源代码中的有效常量。 布尔值和零以明显的方式编写 (, , ). 浮点数以十六进制书写, 以保持完全精度。 字符串写在双引号之间, 必要时使用转义序列以确保 Lua解释器可以安全地读回它。 例如,调用qtruefalsenil

     string.format('%q', 'a string with "quotes" and \n new line')

可能会产生字符串:

     "a string with \"quotes\" and \
      new line"

此说明符不支持修饰符(标志、宽度、精度)。

转换说明符 、 、 和 都需要一个数字作为参数。 说明符 、 、 、 、 和 需要一个整数。 当 Lua 使用 C89 编译器编译时, 说明符和(十六进制浮点数) 不支持修饰符。AaEefGgcdiouXxAa

说明符需要一个字符串; 如果其参数不是字符串, 它被转换为遵循与 tostring 相同的规则。 如果说明符有任何修饰符, 相应的字符串参数不应包含嵌入的零。s

说明符设置指针的格式 lua_topointer返回。 这为表、用户数据、 线程、字符串和函数。 对于其他值(数字、零、布尔值), 此说明符生成一个字符串,表示 指针 。pNULL

string.gmatch (s, pattern [, init])

返回一个迭代器函数,该函数, 每次调用时, 返回下一个捕获自(请参阅 §6.4.1) 在字符串上。 如果未指定捕获, 然后在每次调用中生成整个匹配项。 第三个可选数值参数指定 从哪里开始搜索; 其默认值为 1,可以为负数。patternspatterninit

例如,以下循环 将迭代字符串中的所有单词, 每行打印一个:s

     s = "hello world from Lua"
     for w in string.gmatch(s, "%a+") do
       print(w)
     end

下一个示例从 给定字符串到表中:key=value

     t = {}
     s = "from=world, to=Lua"
     for k, v in string.gmatch(s, "(%w+)=(%w+)") do
       t[k] = v
     end

对于此函数,模式开头的插入符号 '' 不会 作为锚点工作,因为这会阻止迭代。^

string.gsub (s, pattern, repl [, n])

返回其中所有(或第一个,如果给定)的副本 (见 §6.4.1) 的出现次数 替换为 指定的替换字符串 , 可以是字符串、表或函数。 还返回,作为其第二个值, 发生的匹配总数。 这个名字来自Global SUBstitutionsnpatternreplgsubgsub

如果是一个字符串,则其值用于替换。 该角色用作转义字符: 形式的任何序列 , d 介于 1 和 9 之间, 代表捕获的第 d 个子字符串的值; 序列代表整个比赛; 该序列代表单个 .repl%repl%d%0%%%

如果是表,则查询每个匹配项的表, 使用第一个捕获作为键。repl

如果是一个函数,那么每次 发生匹配,所有捕获的子字符串作为参数传递, 挨次。repl

无论如何, 如果模式未指定捕获, 然后它的行为就好像整个模式都在捕获中一样。

如果表查询或函数调用返回的值 是一个字符串或一个数字, 然后它被用作替换字符串; 否则,如果它是的或, 那么就没有替代品了 (即,原始匹配项保留在字符串中)。

以下是一些示例:

     x = string.gsub("hello world", "(%w+)", "%1 %1")
     --> x="hello hello world world"
     
     x = string.gsub("hello world", "%w+", "%0 %0", 1)
     --> x="hello hello world"
     
     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
     --> x="world hello Lua from"
     
     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
     --> x="home = /home/roberto, user = roberto"
     
     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
           return load(s)()
         end)
     --> x="4+5 = 9"
     
     local t = {name="lua", version="5.4"}
     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
     --> x="lua-5.4.tar.gz"

string.len (s)

Receives a string and returns its length. The empty string has length 0. Embedded zeros are counted, so has length 5. """a\000bc\000"

string.lower (s)

Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale.

string.match (s, pattern [, init])

Looks for the first match of the (see §6.4.1) in the string . If it finds one, then returns the captures from the pattern; otherwise it returns fail. If specifies no captures, then the whole match is returned. A third, optional numeric argument specifies where to start the search; its default value is 1 and can be negative. patternsmatchpatterninit

string.pack (fmt, v1, v2, ···)

Returns a binary string containing the values , , etc. serialized in binary form (packed) according to the format string (see §6.4.2). v1v2fmt

string.packsize (fmt)

Returns the length of a string resulting from string.pack with the given format. The format string cannot have the variable-length options '' or '' (see §6.4.2). sz

string.rep (s, n [, sep])

Returns a string that is the concatenation of copies of the string separated by the string . The default value for is the empty string (that is, no separator). Returns the empty string if is not positive. nssepsepn

(Note that it is very easy to exhaust the memory of your machine with a single call to this function.)

string.reverse (s)

Returns a string that is the string reversed. s

string.sub (s, i [, j])

Returns the substring of that starts at and continues until ; and can be negative. If is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call returns a prefix of with length , and (for a positive ) returns a suffix of with length . sijijjstring.sub(s,1,j)sjstring.sub(s, -i)isi

If, after the translation of negative indices, is less than 1, it is corrected to 1. If is greater than the string length, it is corrected to that length. If, after these corrections, is greater than , the function returns the empty string. ijij

string.unpack (fmt, s [, pos])

Returns the values packed in string (see string.pack) according to the format string (see §6.4.2). An optional marks where to start reading in (default is 1). After the read values, this function also returns the index of the first unread byte in . sfmtposss

string.upper (s)

Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale.

6.4.1 – Patterns

Patterns in Lua are described by regular strings, which are interpreted as patterns by the pattern-matching functions string.find, string.gmatch, string.gsub, and string.match. This section describes the syntax and the meaning (that is, what they match) of these strings.

Character Class:

character class is used to represent a set of characters. The following combinations are allowed in describing a character class:

  • x(where x is not one of the magic characters ) represents the character x itself. ^$()%.[]*+-?
  • .(a dot) represents all characters.
  • %arepresents all letters.
  • %crepresents all control characters.
  • %drepresents all digits.
  • %grepresents all printable characters except space.
  • %lrepresents all lowercase letters.
  • %prepresents all punctuation characters.
  • %srepresents all space characters.
  • %urepresents all uppercase letters.
  • %wrepresents all alphanumeric characters.
  • %xrepresents all hexadecimal digits.
  • %x(where x is any non-alphanumeric character) represents the character x. This is the standard way to escape the magic characters. Any non-alphanumeric character (including all punctuation characters, even the non-magical) can be preceded by a '' to represent itself in a pattern. %
  • [set]represents the class which is the union of all characters in set. A range of characters can be specified by separating the end characters of the range, in ascending order, with a ''. All classes x described above can also be used as components in set. All other characters in set represent themselves. For example, (or ) represents all alphanumeric characters plus the underscore, represents the octal digits, and represents the octal digits plus the lowercase letters plus the '' character. -%[%w_][_%w][0-7][0-7%l%-]-

    You can put a closing square bracket in a set by positioning it as the first character in the set. You can put a hyphen in a set by positioning it as the first or the last character in the set. (You can also use an escape for both cases.)

    The interaction between ranges and classes is not defined. Therefore, patterns like or have no meaning. [%a-z][a-%%]

  • [^set]represents the complement of set, where set is interpreted as above.

For all classes represented by single letters (, , etc.), the corresponding uppercase letter represents the complement of the class. For instance, represents all non-space characters. %a%c%S

The definitions of letter, space, and other character groups depend on the current locale. In particular, the class may not be equivalent to . [a-z]%l

Pattern Item:

pattern item can be

  • a single character class, which matches any single character in the class;
  • a single character class followed by '', which matches sequences of zero or more characters in the class. These repetition items will always match the longest possible sequence; *
  • a single character class followed by '', which matches sequences of one or more characters in the class. These repetition items will always match the longest possible sequence; +
  • a single character class followed by '', which also matches sequences of zero or more characters in the class. Unlike '', these repetition items will always match the shortest possible sequence; -*
  • a single character class followed by '', which matches zero or one occurrence of a character in the class. It always matches one occurrence if possible; ?
  • %n, for n between 1 and 9; such item matches a substring equal to the n-th captured string (see below);
  • %bxy, where x and y are two distinct characters; such item matches strings that start with x, end with y, and where the x and y are balanced. This means that, if one reads the string from left to right, counting +1 for an x and -1 for a y, the ending y is the first y where the count reaches 0. For instance, the item matches expressions with balanced parentheses. %b()
  • %f[set], a frontier pattern; such item matches an empty string at any position such that the next character belongs to set and the previous character does not belong to set. The set set is interpreted as previously described. The beginning and the end of the subject are handled as if they were the character ''. \0
Pattern:

pattern is a sequence of pattern items. A caret '' at the beginning of a pattern anchors the match at the beginning of the subject string. A '' at the end of a pattern anchors the match at the end of the subject string. At other positions, '' and '' have no special meaning and represent themselves. ^$^$

Captures:

A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the substrings of the subject string that match captures are stored (captured) for future use. Captures are numbered according to their left parentheses. For instance, in the pattern , the part of the string matching is stored as the first capture, and therefore has number 1; the character matching "" is captured with number 2, and the part matching "" has number 3. "(a*(.)%w(%s*))""a*(.)%w(%s*)".%s*

As a special case, the capture captures the current string position (a number). For instance, if we apply the pattern on the string , there will be two captures: 3 and 5. ()"()aa()""flaaap"

Multiple matches:

The function string.gsub and the iterator string.gmatch match multiple occurrences of the given pattern in the subject. For these functions, a new match is considered valid only if it ends at least one byte after the end of the previous match. In other words, the pattern machine never accepts the empty string as a match immediately after another match. As an example, consider the results of the following code:

     > string.gsub("abc", "()a*()", print);
     --> 1   2
     --> 3   3
     --> 4   4

The second and third results come from Lua matching an empty string after '' and another one after ''. Lua does not match an empty string after '', because it would end at the same position of the previous match. bca

6.4.2 – Format Strings for Pack and Unpack

The first argument to string.pack, string.packsize, and string.unpack is a format string, which describes the layout of the structure being created or read.

A format string is a sequence of conversion options. The conversion options are as follows:

  • <设置小端序
  • >设置大端序
  • =设置本机字节序
  • n]将最大对齐方式设置为(默认为本机对齐方式)n
  • B有符号字节 (char)
  • B无符号字节 (char)
  • H有符号(本机大小)short
  • H无符号(本机大小)short
  • L有符号(本机大小)long
  • L无符号(本机大小)long
  • J: alua_Integer
  • Jalua_Unsigned
  • T:a(原始大小)size_t
  • i[n]用字节签名 (默认为本机大小)intn
  • I[n]带字节的无符号 (默认为本机大小)intn
  • F:A(原始大小)float
  • D:A(原始大小)double
  • n: alua_Number
  • cn带有字节的固定大小的字符串n
  • z以零结尾的字符串
  • s[n]一个字符串,前面有其长度 编码为带字节的无符号整数 (默认值为nsize_t)
  • x一个字节的填充
  • Xop对齐的空项 根据选项(否则将被忽略)op
  • ':(空格)忽略

(“” 表示可选的整数。 填充、空格和配置除外 (选项“”), 每个选项对应于 String.pack 中的一个参数或 String.Unpack 中的一个结果。[n]xX <=>!

对于选项 “”、“”、“” 和 “”,可以是 1 到 16 之间的任何整数。 所有积分选项检查溢出;string.pack 检查给定的值是否适合给定的大小;string.unpack 检查读取值是否适合 Lua 整数。 对于未签名的选项, Lua 整数也被视为无符号值。!nsninInn

任何格式字符串都以“”开头, 那是 最大对齐方式为 1(无对齐方式) 和原生字节序。!1=

本机字节序假定整个系统是 要么大端,要么小端。 打包函数将无法正确模拟行为 的混合端格式。

对齐方式如下: 对于每个选项, 格式获得额外的填充,直到数据开始 偏移量是最小值之间的倍数 选项大小和最大对齐方式; 此最小值必须为 2 的幂。 选项 “” 和 “” 未对齐; 选项 “” 遵循其起始整数的对齐方式。czs

所有填充都由string.pack填充零,并由string.unpack忽略。

6.5 – UTF-8 支持

此库提供对 UTF-8 编码的基本支持。 它在表 utf8 中提供了所有功能。 此库不提供对 Unicode 其他的任何支持 比编码的处理。 任何需要字符含义的操作, 如字符分类,则超出其范围。

除非另有说明, 所有需要字节位置作为参数的函数 假设给定的位置是字节序列的开头 或 1 加上主题字符串的长度。 就像在字符串库中一样, 负索引从字符串末尾开始计数。

创建字节序列的函数 接受 之前的所有值 , 如原始 UTF-8 规范中所定义; 这意味着最多六个字节的字节序列。0x7FFFFFFF

解释字节序列的函数仅接受 有效序列(格式良好且不会过长)。 默认情况下,它们只接受字节序列 产生有效的 Unicode 代码点, 拒绝大于和代理项的值。 布尔参数,如果可用, 解除这些检查, 以便接受以下的所有值。 (格式不正确,超长的序列仍然被拒绝。10FFFFlax0x7FFFFFFF

utf8.char (···)

接收零个或多个整数, 将每个字节转换为其相应的 UTF-8 字节序列 并返回一个字符串,其中包含所有这些序列的串联。

utf8.charpattern

模式(字符串,不是函数)“” (见 §6.4.1), 它正好匹配一个 UTF-8 字节序列, 假设主题是有效的 UTF-8 字符串。[\0-\x7F\xC2-\xFD][\x80-\xBF]*

utf8.codes (s [, lax])

返回值,以便构造

     for p, c in utf8.codes(s) do body end

将迭代字符串中的所有 UTF-8 字符, 作为位置(以字节为单位)和代码点 每个字符。 如果它遇到任何无效的字节序列,则会引发错误。spc

utf8.codepoint (s [, i [, j [, lax]]])

返回字节位置和(均包含)之间开始的所有字符的代码点(整数)。 的默认值为 1,for 的默认值为 。 如果它遇到任何无效的字节序列,则会引发错误。sijiji

utf8.len (s [, i [, j [, lax]]])

返回字符串中从位置和(包括两者)之间开始的 UTF-8 字符数。 的默认值为 1,for 的默认值为 -1。 如果它找到任何无效的字节序列, 返回 fail 加上第一个无效字节的位置。sijij

utf8.offset (s, n [, i])

返回 的第 -个字符的编码开始的位置(以字节为单位)。 负数在位置之前获取字符。 当非负数时,默认值为 1 否则, 这样就可以从字符串末尾获取第 -个字符的偏移量。 如果指定的字符不在主题中 也不是在它结束后, 该函数返回失败nsiniin#s + 1utf8.offset(s, -n)n

作为特例, 当为 0 时,该函数返回编码的开始 的字符,该字符包含 的第 个字节。nis

此函数假定 是有效的 UTF-8 字符串。s

6.6 – 表操作

此库提供用于表操作的通用函数。 它在表提供其所有功能。

请记住,每当操作需要表的长度时, 有关长度运算符的所有注意事项均适用(参见 §3.4.7)。 所有函数都忽略非数字键 在作为参数给出的表中。

table.concat (list [, sep [, i [, j]]])

给定一个列表,其中所有元素都是字符串或数字, 返回字符串 。 的默认值为空字符串, 的默认值为 1, 的默认值为 。 如果大于 ,则返回空字符串。list[i]..sep..list[i+1] ··· sep..list[j]sepij#listij

table.insert (list, [pos,] value)

在 中的位置插入元素 向上移动元素. 的默认值为 , 以便呼叫在末尾插入 的 列表 .valueposlistlist[pos], list[pos+1], ···, list[#list]pos#list+1table.insert(t,x)xt

table.move (a1, f, e, t [,a2])

将元素从表移动到表, 执行等效于以下内容的操作 多重分配:。 的缺省值为 。 目标范围可以与源范围重叠。 要移动的元素数必须适合 Lua 整数。a1a2a2[t],··· = a1[f],···,a1[e]a2a1

返回目标表 。a2

table.pack (···)

返回一个新表,其中所有参数都存储在键 1、2 等中。 并带有一个包含参数总数的字段“”。 请注意,生成的表可能不是一个序列, 如果某些参数为n

table.remove (list [, pos])

从位置 的元素中删除 , 返回已删除元素的值。 when 是介于 1 和 之间的整数 , 它向下移动元素并擦除元素; 当为 0 时,索引也可以为 0, 或。listpospos#listlist[pos+1], list[pos+2], ···, list[#list]list[#list]pos#list#list + 1

的默认值为 , 以便调用删除最后一个元素 的 列表 .pos#listtable.remove(l)l

table.sort (list [, comp])

按给定顺序就对列表元素进行排序, 从 到 。 如果给出, 那么它必须是一个接收两个列表元素的函数 并在第一个元素必须出现时返回 true 在最终顺序中的第二个之前, 因此,在排序之后,暗示. 如果没有给出, 则改用标准 Lua 运算符。list[1]list[#list]compi <= jnot comp(list[j],list[i])comp<

该函数必须定义一致的顺序; 更正式地说,函数必须定义一个严格的弱顺序。 (弱订单类似于总订单, 但它可以等同于不同的元素以进行比较。comp

排序算法不稳定: 给定顺序认为不同的元素相等 它们的相对位置可能会因排序而改变。

table.unpack (list [, i [, j]])

返回给定列表中的元素。 此函数等效于

     return list[i], list[i+1], ···, list[j]

缺省情况下,为 1 且为 。ij#list

6.7 – 数学函数

该库提供基本的数学函数。 它在表数学中提供其所有函数和常量。 带有注释 “” 的函数给出 整数参数的整数结果 以及非整数参数的浮点结果。 舍入函数math.ceil,math.floor和math.modf在结果适合整数范围内时返回一个整数, 否则为浮点数。integer/float

math.abs (x)

返回 和 之间的最大值。(整数/浮点数)x-x

math.acos (x)

返回 (以弧度为单位)的弧余弦值。x

math.asin (x)

返回 (以弧度为单位)的弧正弦值。x

math.atan (y [, x])

返回 (以弧度为单位) 的反正切值, 使用两个参数的符号来查找 结果的象限。 它还正确处理为零的情况。y/xx

的默认值为 1, 以便调用返回 的反正切值。xmath.atan(y)y

math.ceil (x)

返回大于或等于的最小整数值。x

math.cos (x)

返回余弦值(假定以弧度为单位)。x

math.deg (x)

将角度从弧度转换为度。x

math.exp (x)

返回值 ex(其中是自然对数的底数)。e

math.floor (x)

返回小于或等于 的最大整数值。x

math.fmod (x, y)

返回 的除以的余数,该除法将商舍入为零。(整数/浮点数)xy

math.huge

浮点值 , 大于任何其他数值的值。HUGE_VAL

math.log (x [, base])

返回给定底数中的对数。 的默认值为 e(以便函数返回 的自然对数 )。xbasex

math.max (x, ···)

返回具有最大值的参数, 根据Lua运营商的说法。<

math.maxinteger

具有整数最大值的整数。

math.min (x, ···)

返回具有最小值的参数, 根据Lua运营商的说法。<

math.mininteger

具有整数的最小值的整数。

math.modf (x)

返回 的整数部分和小数部分。 它的第二个结果始终是浮点数。xx

math.pi

π的值。

math.rad (x)

将角度从度转换为弧度。x

math.random ([m [, n]])

当调用时没有参数, 返回具有均匀分布的伪随机浮点数 在 [0,1] 范围内。 当使用两个整数和 调用时,返回一个伪随机整数 均匀分布在 [m, n] 范围内。 呼吁,为积极, 等效于 。 调用生成一个整数 所有位(伪)随机。mnmath.randommath.random(n)nmath.random(1,n)math.random(0)

此函数使用算法生成 伪随机64位整数, 这是参数为 0 的调用的结果。 其他结果(范围和浮点数) 是从这些整数中提取的无偏。xoshiro256**

Lua 初始化其伪随机生成器,相当于 调用没有参数的 math.randomseed, 所以应该产生 每次程序运行时的结果序列不同。math.random

math.randomseed ([x [, y]])

当使用至少一个参数调用时, 整数参数和 加入到 128 位种子中 用于重新初始化伪随机生成器; 相等的种子产生相等的数字序列。 的默认值为零。xyy

当调用时没有参数, Lua 生成一个种子 随机性的弱尝试。

此函数返回两个种子组件 得到有效利用, 因此,再次设置它们会重复该序列。

确保初始状态所需的随机性水平 (或者相反,要有一个确定性的序列, 例如在调试程序时), 你应该用显式参数调用math.randomseed。

math.sin (x)

返回 的正弦值(假定以弧度为单位)。x

math.sqrt (x)

返回 的平方根。 (也可以使用该表达式来计算此值。xx^0.5

math.tan (x)

返回 的正切值(假定以弧度为单位)。x

math.tointeger (x)

如果该值可转换为整数, 返回该整数。 否则,返回将失败x

math.type (x)

如果为整数,则返回 “”, “”如果是浮点数, 如果不是数字,则失败integerxfloatx

math.ult (m, n)

返回布尔值,当且仅当整数低于整数时返回 true,当 它们被比较为无符号整数。mn

6.8 – 输入和输出设施

I/O 库为文件操作提供了两种不同的样式。 第一个使用隐式文件句柄; 也就是说,有设置默认输入文件和 默认输出文件, 所有输入/输出操作都是在这些默认文件上完成的。 第二种样式使用显式文件句柄。

使用隐式文件句柄时, 所有操作均由表 IO 提供。 使用显式文件句柄时, 操作 io.open 返回文件句柄 然后所有操作都作为文件句柄的方法提供。

文件句柄的元表提供元方法 为了和那个尝试 以在调用时关闭文件。__gc__close

该表还提供 三个预定义的文件句柄,其通常含义来自 C:io.stdin、io.stdout 和 io.stderr。 I/O 库永远不会关闭这些文件。io

除非另有说明, 所有 I/O 函数在失败时返回失败, 加上错误消息作为第二个结果,并且 与系统相关的错误代码作为第三个结果, 以及一些关于成功的非虚假价值。 在非 POSIX 系统上, 错误消息和错误代码的计算 万一出现错误 可能不是线程安全的, 因为它们依赖于全局 C 变量。errno

io.close ([file])

等效于 。 如果没有 ,将关闭默认输出文件。file:close()file

io.flush ()

等效于 。io.output():flush()

io.input ([file])

当使用文件名调用时,它会打开命名文件(在文本模式下), 并将其句柄设置为默认输入文件。 使用文件句柄调用时, 它只是将此文件句柄设置为默认输入文件。 当调用时没有参数, 它返回当前默认输入文件。

如果出现错误,此函数会引发错误, 而不是返回错误代码。

io.lines ([filename, ···])

在阅读模式下打开给定的文件名 并返回一个迭代器函数 就像在打开的文件上一样工作。 当迭代器函数无法读取任何值时, 它会自动关闭文件。 除了迭代器函数之外,还返回其他三个值: 两个 nil 值作为占位符, 加上创建的文件句柄。 因此,当在泛型 for 循环中使用时, 如果循环被 错误或中断file:lines(···)io.lines

调用(没有文件名)是等效的 自; 也就是说,它遍历默认输入文件的行。 在这种情况下,迭代器不会在循环结束时关闭文件。io.lines()io.input():lines("l")

如果打开文件时出错, 此函数引发错误, 而不是返回错误代码。

io.open (filename [, mode])

此函数打开一个文件, 在字符串中指定的模式下。 如果成功, 它返回一个新的文件句柄。mode

该字符串可以是以下任何字符串:mode

  • r”:读取模式(默认);
  • w”:写入模式;
  • a”:追加模式;
  • r+”:更新模式,保留所有以前的数据;
  • w+”:更新模式,之前的所有数据都被擦除;
  • A+”:追加更新模式,保留以前的数据, 只允许在文件末尾写入。

字符串末尾也可以有一个 '', 在某些系统中需要以二进制模式打开文件。modeb

io.output ([file])

与 io.input 类似,但对默认输出文件进行操作。

io.popen (prog [, mode])

此功能取决于系统,不可用 在所有平台上。

在单独的进程中启动程序并返回 可用于从此程序读取数据的文件句柄 (如果是 ,则为默认值) 或将数据写入此程序 (如果是)。progmode"r"mode"w"

io.read (···)

等效于 。io.input():read(···)

io.tmpfile ()

如果成功, 返回临时文件的句柄。 此文件在更新模式下打开 并在程序结束时自动删除。

io.type (obj)

检查是否为有效的文件句柄。 返回字符串,如果是打开的文件句柄,如果是关闭的文件句柄, 如果不是文件句柄,则失败obj"file"obj"closed file"objobj

io.write (···)

等效于 。io.output():write(···)

file:close ()

关闭。 请注意,文件在以下情况下会自动关闭 他们的手柄是垃圾收集, 但这需要不可预测的时间才能发生。file

关闭使用 io.popen 创建的文件句柄时,file:close 返回相同的值 由 os.execute 返回。

file:flush ()

Saves any written data to . file

file:lines (···)

Returns an iterator function that, each time it is called, reads the file according to the given formats. When no format is given, uses "" as a default. As an example, the construction l

     for c in file:lines(1) do body end

will iterate over all characters of the file, starting at the current position. Unlike io.lines, this function does not close the file when the loop ends.

file:read (···)

Reads the file , according to the given formats, which specify what to read. For each format, the function returns a string or a number with the characters read, or fail if it cannot read data with the specified format. (In this latter case, the function does not read subsequent formats.) When called without arguments, it uses a default format that reads the next line (see below). file

The available formats are

  • "n": reads a numeral and returns it as a float or an integer, following the lexical conventions of Lua. (The numeral may have leading whitespaces and a sign.) This format always reads the longest input sequence that is a valid prefix for a numeral; if that prefix does not form a valid numeral (e.g., an empty string, "", or "") or it is too long (more than 200 characters), it is discarded and the format returns fail0x3.4e-
  • "a": reads the whole file, starting at the current position. On end of file, it returns the empty string; this format never fails.
  • "l": reads the next line skipping the end of line, returning fail on end of file. This is the default format.
  • "L": reads the next line keeping the end-of-line character (if present), returning fail on end of file.
  • numberreads a string with up to this number of bytes, returning fail on end of file. If is zero, it reads nothing and returns an empty string, or fail on end of file. number

The formats "" and "" should be used only for text files. lL

file:seek ([whence [, offset]])

Sets and gets the file position, measured from the beginning of the file, to the position given by plus a base specified by the string , as follows: offsetwhence

  • "set": base is position 0 (beginning of the file);
  • "cur": base is current position;
  • "end": base is end of file;

In case of success, returns the final file position, measured in bytes from the beginning of the file. If fails, it returns fail, plus a string describing the error. seekseek

The default value for is , and for is 0. Therefore, the call returns the current file position, without changing it; the call sets the position to the beginning of the file (and returns 0); and the call sets the position to the end of the file, and returns its size. whence"cur"offsetfile:seek()file:seek("set")file:seek("end")

file:setvbuf (mode [, size])

Sets the buffering mode for a file. There are three available modes:

  • "no": no buffering.
  • "full": full buffering.
  • "line": line buffering.

For the last two cases, is a hint for the size of the buffer, in bytes. The default is an appropriate size. size

The specific behavior of each mode is non portable; check the underlying ISO C function in your platform for more details. setvbuf

file:write (···)

Writes the value of each of its arguments to . The arguments must be strings or numbers. file

In case of success, this function returns . file

6.9 – Operating System Facilities

This library is implemented through table os.

os.clock ()

Returns an approximation of the amount in seconds of CPU time used by the program, as returned by the underlying ISO C function . clock

os.date ([format [, time]])

Returns a string or a table containing date and time, formatted according to the given string . format

If the argument is present, this is the time to be formatted (see the os.time function for a description of this value). Otherwise, formats the current time. timedate

If starts with '', then the date is formatted in Coordinated Universal Time. After this optional character, if is the string "", then returns a table with the following fields: , (1–12), (1–31), (0–23), (0–59), (0–61, due to leap seconds), (weekday, 1–7, Sunday is 1), (day of the year, 1–366), and (daylight saving flag, a boolean). This last field may be absent if the information is not available. format!format*tdateyearmonthdayhourminsecwdayydayisdst

If is not "", then returns the date as a string, formatted according to the same rules as the ISO C function . format*tdatestrftime

If is absent, it defaults to "", which gives a human-readable date and time representation using the current locale. format%c

On non-POSIX systems, this function may be not thread safe because of its reliance on C function and C function . gmtimelocaltime

os.difftime (t2, t1)

Returns the difference, in seconds, from time to time (where the times are values returned by os.time). In POSIX, Windows, and some other systems, this value is exactly -t1t2t2t1

os.execute ([command])

This function is equivalent to the ISO C function . It passes to be executed by an operating system shell. Its first result is true if the command terminated successfully, or fail otherwise. After this first result the function returns a string plus a number, as follows: systemcommand

  • "exit": the command terminated normally; the following number is the exit status of the command.
  • "signal": the command was terminated by a signal; the following number is the signal that terminated the command.

When called without a , returns a boolean that is true if a shell is available. commandos.execute

os.exit ([code [, close]])

Calls the ISO C function to terminate the host program. If is true, the returned status is ; if is false, the returned status is ; if is a number, the returned status is this number. The default value for is trueexitcodeEXIT_SUCCESScodeEXIT_FAILUREcodecode

If the optional second argument is true, the function closes the Lua state before exiting (see lua_close). close

os.getenv (varname)

Returns the value of the process environment variable or fail if the variable is not defined. varname

os.remove (filename)

Deletes the file (or empty directory, on POSIX systems) with the given name. If this function fails, it returns fail plus a string describing the error and the error code. Otherwise, it returns true.

os.rename (oldname, newname)

Renames the file or directory named to . If this function fails, it returns fail, plus a string describing the error and the error code. Otherwise, it returns true. oldnamenewname

os.setlocale (locale [, category])

Sets the current locale of the program. is a system-dependent string specifying a locale; is an optional string describing which category to change: , , , , , or ; the default category is . The function returns the name of the new locale, or fail if the request cannot be honored. localecategory"all""collate""ctype""monetary""numeric""time""all"

If is the empty string, the current locale is set to an implementation-defined native locale. If is the string "", the current locale is set to the standard C locale. localelocaleC

When called with nil as the first argument, this function only returns the name of the current locale for the given category.

This function may be not thread safe because of its reliance on C function . setlocale

os.time ([table])

Returns the current time when called without arguments, or a time representing the local date and time specified by the given table. This table must have fields , , and , and may have fields (default is 12), (default is 0), (default is 0), and (default is nil). Other fields are ignored. For a description of these fields, see the os.date function. yearmonthdayhourminsecisdst

When the function is called, the values in these fields do not need to be inside their valid ranges. For instance, if is -10, it means 10 seconds before the time specified by the other fields; if is 1000, it means 1000 hours after the time specified by the other fields. sechour

The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the number of seconds since some given start time (the "epoch"). In other systems, the meaning is not specified, and the number returned by can be used only as an argument to os.date and os.difftime. time

When called with a table, also normalizes all the fields documented in the os.date function, so that they represent the same time as before the call but with values inside their valid ranges. os.time

os.tmpname ()

Returns a string with a file name that can be used for a temporary file. The file must be explicitly opened before its use and explicitly removed when no longer needed.

In POSIX systems, this function also creates a file with that name, to avoid security risks. (Someone else might create the file with wrong permissions in the time between getting the name and creating the file.) You still have to open the file to use it and to remove it (even if you do not use it).

When possible, you may prefer to use io.tmpfile, which automatically removes the file when the program ends.

6.10 – The Debug Library

This library provides the functionality of the debug interface (§4.7) to Lua programs. You should exert care when using this library. Several of its functions violate basic assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside; that userdata metatables cannot be changed by Lua code; that Lua programs do not crash) and therefore can compromise otherwise secure code. Moreover, some functions in this library may be slow.

All functions in this library are provided inside the debug table. All functions that operate over a thread have an optional first argument which is the thread to operate over. The default is always the current thread.

debug.debug ()

Enters an interactive mode with the user, running each string that the user enters. Using simple commands and other debug facilities, the user can inspect global and local variables, change their values, evaluate expressions, and so on. A line containing only the word finishes this function, so that the caller continues its execution. cont

Note that commands for are not lexically nested within any function and so have no direct access to local variables. debug.debug

debug.gethook ([thread])

Returns the current hook settings of the thread, as three values: the current hook function, the current hook mask, and the current hook count, as set by the debug.sethook function.

Returns fail if there is no active hook.

debug.getinfo ([thread,] f [, what])

返回包含有关函数信息的表。 你可以直接给出函数 或者你可以给出一个数字作为 的值, 这意味着在调用堆栈级别运行的函数 给定线程: 级别 0 是当前函数(本身); 级别 1 是调用的函数(尾部调用除外,它不计入堆栈); 等等。 如果 是一个大于活动函数数的数字, 然后返回失败ffgetinfogetinfofgetinfo

返回的表可以包含lua_getinfo返回的所有字段, 使用描述要填写的字段的字符串。 的默认值是获取所有可用信息, 有效行表除外。 如果存在, 选项 '' 添加一个以函数本身命名的字段。 如果存在, 选项 '' 添加一个以 表命名的字段 有效行。whatwhatffuncLactivelines

例如,表达式返回 当前函数的名称, 如果能找到合理的名称, 表达式返回一个包含所有可用信息的表 关于打印功能。debug.getinfo(1,"n").namedebug.getinfo(print)

debug.getlocal ([thread,] f, local)

此函数返回局部变量的名称和值 在堆栈级别使用函数的索引。 此函数不仅访问显式局部变量, 还有参数和临时值。localf

第一个参数或局部变量的索引为 1,依此类推, 按照它们在代码中声明的顺序, 仅计算处于活动状态的变量 在函数的当前范围内。 编译时常量可能不会出现在此清单中, 如果它们被编译器优化掉了。 负指数是指变量参数; -1 是第一个 vararg 参数。 如果给定索引没有变量,则该函数返回 failed, 并在级别超出范围的情况下调用时引发错误。 (你可以调用debug.getinfo来检查该级别是否有效。

以 '' 开头的变量名称(左括号) 表示没有已知名称的变量 (内部变量,如环路控制变量, 以及保存的没有调试信息的块中的变量)。(

该参数也可以是一个函数。 在这种情况下,仅返回函数参数的名称。fgetlocal

debug.getmetatable (value)

返回给定的元表,如果没有元表,则返回 nil 的元表。value

debug.getregistry ()

返回注册表表(参见 §4.3)。

debug.getupvalue (f, up)

此函数返回上值的名称和值 带有函数的索引。 如果给定索引没有上升值,则该函数返回 failedupf

(对于 Lua 函数, upvalue 是函数使用的外部局部变量, 因此,这被包括在它的关闭中。

对于 C 函数,此函数使用空字符串作为所有上行值的名称。""

变量名称 ''(询问标记) 表示没有已知名称的变量 (来自没有调试信息的保存块的变量)。?

debug.getuservalue (u, n)

返回关联的第 -个用户值 到用户数据加上布尔值,如果用户数据没有该值,则为 falsenu

debug.sethook ([thread,] hook, mask [, count])

将给定函数设置为调试挂钩。 字符串和数字描述 何时调用钩子。 字符串掩码可以具有以下字符的任意组合, 具有给定的含义:maskcount

  • 'c':每次 Lua 调用函数时都会调用钩子;
  • 'r':每次 Lua 从函数返回时都会调用钩子;
  • 'l':每次 Lua 输入新代码行时都会调用钩子。

此外 与零不同, 钩子也会在每条指令后调用。countcount

当在没有参数的情况下调用时,debug.sethook 会关闭钩子。

调用钩子时,它的第一个参数是一个字符串 描述触发其调用的事件:、、、 和 。 对于线路事件, 钩子还获取新的行号作为其第二个参数。 在钩子内, 您可以致电 2 级以获取有关以下内容的更多信息 运行函数。 (级别 0 是函数, 级别 1 是钩子函数。"call""tail call""return""line""count"getinfogetinfo

debug.setlocal ([thread,] level, local, value)

此函数将值分配给局部变量 在堆栈级别使用函数的索引。 如果没有本地函数,则返回 fail 具有给定索引的变量, 并在超出范围调用时引发错误。 (您可以致电检查该级别是否有效。 否则,它将返回局部变量的名称。valuelocallevellevelgetinfo

请参阅 debug.getlocal 以获取有关以下内容的更多信息 变量索引和名称。

debug.setmetatable (value, table)

将给定的元表设置为给定的元表(可以为 nil)。 返回。valuetablevalue

debug.setupvalue (f, up, value)

此函数将值分配给上值 带有函数的索引。 如果没有上值,函数返回失败 与给定的索引。 否则,它将返回上行值的名称。valueupf

有关upvalues的更多信息,请参阅debug.getupvalue。

debug.setuservalue (udata, value, n)

将给定设置为 与给定 关联的第 -个用户值。 必须是完整的用户数据。valuenudataudata

返回 或者,如果用户数据没有该值,则失败udata

debug.traceback ([thread,] [message [, level]])

如果存在,但既不是字符串也不是, 此函数返回而不进行进一步处理。 否则 它返回一个字符串,其中包含调用堆栈的回溯。 附加可选字符串 在回溯的开头。 可选数字指示哪个级别 启动回溯 (默认为1,函数调用)。messagemessagemessageleveltraceback

debug.upvalueid (f, n)

返回唯一标识符(作为轻用户数据) 对于从给定函数编号的上值。n

这些唯一标识符允许程序检查是否不同 闭包共享升值。 共享升值的 Lua 闭包 (即,访问相同的外部局部变量) 将为这些升值指数返回相同的 ID。

debug.upvaluejoin (f1, n1, f2, n2)

使 Lua 闭包的第 -th 上值是指 Lua 闭包的第 -th 上值。n1f1n2f2

7 – Lua 独立

虽然Lua被设计为一种扩展语言, 嵌入到主机 C 程序中, 它也经常用作独立语言。 Lua作为独立语言的口译员, 简称为 , 随标准发行版一起提供。 独立口译员包括 所有标准库。 它的用法是:lua

     lua [options] [script [args]]

选项包括:

  • -e stat:执行字符串 stat;
  • -i运行脚本后进入交互模式;
  • -l mod: “需要”模组并分配 结果到全局模组;
  • -l g=mod: “需要”模组并分配 结果到全局 G;
  • -v打印版本信息;
  • -E忽略环境变量;
  • -W打开警告;
  • --停止处理选项;
  • -作为文件执行并停止处理选项。stdin

(该表单在版本 5.4.4 中引入。-l g=mod

处理完其选项后,运行给定的脚本。 在没有参数的情况下调用时,其行为与标准输入 () 是终端时一样, 否则。lualualua -v -istdinlua -

在没有选项的情况下调用时, 解释器检查环境变量LUA_INIT_5_4(如果未定义版本化名称,则LUA_INIT) 在运行任何参数之前。 如果变量内容具有 的格式为 , 然后执行该文件。 否则,执行字符串本身。-E@filenamelualua

当使用选项 调用时, Lua 不咨询任何环境变量。 特别 package.path 和 package.cpath 的值是使用 中定义的默认路径设置的。-Eluaconf.h

选项 、 和 在 中处理 它们出现的顺序。 例如,像这样的调用-e-l-W

     $ lua -e 'a=1' -llib1 script.lua

将首先设置为 1,然后需要库, 最后运行没有参数的文件。 (这是外壳提示符。您的提示可能会有所不同。alib1script.lua$

在运行任何代码之前,收集所有命令行参数 在名为 的全局表中。 脚本名称转到索引 0, 脚本名称后的第一个参数转到索引 1, 等等。 脚本名称之前的任何参数 (即解释器名称及其选项) 转到负指数。 例如,在通话中luaarg

     $ lua -la b.lua t1 t2

表格是这样的:

     arg = { [-2] = "lua", [-1] = "-la",
             [0] = "b.lua",
             [1] = "t1", [2] = "t2" }

如果调用中没有脚本, 解释器名称转到索引 0, 其次是其他论点。 例如,调用

     $ lua -e "print(arg[1])"

将打印 “”。 如果有脚本, 使用参数调用脚本 , ···, 。 像Lua中的所有块一样, 该脚本被编译为可变参数函数。-earg[1]arg[#arg]

在交互模式下, Lua反复提示并等待排队。 读完一行后, Lua首先尝试将这条线解释为一个表达式。 如果成功,它将打印其值。 否则,它将该行解释为语句。 如果你写了一个不完整的陈述, 口译员等待完成 通过发出不同的提示。

如果全局变量_PROMPT包含字符串, 然后其值用作提示。 同样,如果全局变量_PROMPT2包含字符串, 其值用作辅助提示 (在不完整的声明期间发布)。

如果脚本中出现未受保护的错误, 解释器将错误报告给标准错误流。 如果错误对象不是字符串,而是 有一个元方法, 解释器调用此元方法来生成最终消息。 否则,解释器将错误对象转换为字符串 并向其添加堆栈回溯。 当警告打开时, 它们只是打印在标准错误输出中。__tostring

正常完成时, 解释器关闭其主 Lua 状态 (见lua_close)。 脚本可以通过以下方式避免此步骤 调用 os.exit 以终止。

允许将 Lua 用作 Unix系统中的脚本解释器, Lua 跳过文件块的第一行,如果它以 开头。 因此,Lua脚本可以制作成可执行程序 通过使用和表单, 如#chmod +x#!

     #!/usr/local/bin/lua

答案是肯定的 Lua 解释器的位置在您的机器中可能不同。 如果在您的 中 , 然后luaPATH

     #!/usr/bin/env lua

是一种更便携的解决方案。

8 – 与先前版本不兼容

在这里,我们列出了在移动应用程序时可能会发现的不兼容性 从 Lua 5.3 到 Lua 5.4。

您可以通过编译 Lua 来避免一些不兼容 适当的选项(请参阅文件 )。 然而 所有这些兼容性选项都将在将来删除。 通常情况下, 当这些兼容性选项出现兼容性问题时 被删除。 所以,只要有机会, 您应该尝试使用编译的Lua版本来测试您的代码 关闭所有兼容性选项。 这将简化向较新版本Lua的过渡。luaconf.h

Lua 版本始终可以通过以下方式更改 C API: 不暗示程序中的源代码更改, 例如常量的数值 或将函数实现为宏。 因此 你永远不应该假设二进制文件在 不同的 Lua 版本。 始终在以下情况下重新编译 Lua API 的客户端 使用新版本。

同样,Lua 版本总是可以更改内部表示 预编译块; 预编译块在不同的Lua版本之间不兼容。

官方发行中的标准路径可以 在版本之间更改。

8.1 – 语言不兼容

  • 字符串对数字的强制 算术运算和按位运算 已从核心语言中删除。 字符串库执行类似的工作 用于算术(但不适用于按位)运算 使用字符串元方法。 但是,与以前的版本不同, 新的实现保留了数字的隐式类型 在字符串中。 例如,现在的结果是一个整数, 不是浮动。"1" + "2"
  • 溢出的文字十进制整数常量被读取为浮点数, 而不是缠绕。 您可以对此类常量使用十六进制表示法,如果 想要旧的行为 (将它们读取为带有环绕的整数)。
  • 已删除使用元方法进行模拟。 需要时,必须显式定义此元方法。__lt__le
  • 数字 for 循环的语义 超过整数在某些细节上发生了变化。 特别是,控制变量永远不会环绕。
  • 如果具有相同标签的标签,则无法声明 goto 的标签 名称可见,即使此其他标签在封闭中声明 块。
  • 完成对象时, Lua 不会忽略不是函数的元方法。 如果存在,将调用任何值。 (不可调用的值将生成警告, 就像调用终结器时的任何其他错误一样。__gc

8.2 – 库中的不兼容性

  • 函数 print 不会调用 tostring 来格式化其参数; 相反,它具有硬连线的此功能。 应使用 修改值的打印方式。__tostring
  • 函数 math.random 使用的伪随机数生成器现在从一个有点随机的种子开始。 此外,它使用不同的算法。
  • 默认情况下,utf8 库中的解码函数 不要接受代理项作为有效的代码点。 这些函数中的额外参数使它们更加宽松。
  • 选项 “” 和 “” 的函数收集垃圾被弃用。 您应该使用新选项“”来设置它们。setpausesetstepmulincremental
  • 函数 io.lines 现在返回四个值, 而不仅仅是一个。 当它用作鞋底时,这可能是一个问题 参数到另一个具有可选参数的函数, 如在 中。 要解决此问题, 您可以将调用括在括号中, 将其结果数调整为 1。load(io.lines(filename, "L"))

8.3 – API 中的不兼容性

  • 完整用户数据现在具有任意数量的关联用户值。 因此,函数 、 和 是 替换为lua_newuserdatauv、lua_setiuservalue和lua_getiuservalue, 其中有一个额外的参数。lua_newuserdatalua_setuservaluelua_getuservalue

    为了兼容,旧名称仍然作为宏工作,假设 单个用户值。 但请注意,用户值为零的用户数据 在内存方面更有效。

  • 函数 lua_resume 有一个额外的参数。 此 out 参数返回 上的值数 协程生成或返回的堆栈顶部。 (在以前的版本中, 这些值是整个堆栈。
  • 函数 lua_version 返回版本号, 而不是版本号的地址。 Lua 核心应该与使用它们的库正常工作 拥有相同内核的静态副本, 所以没有必要检查他们是否使用相同的 地址空间。
  • 常量已删除。 终结器中的错误永远不会传播; 相反,它们会生成警告。LUA_ERRGCMM
  • 选项和函数lua_gc已弃用。 您应该使用新选项来设置它们。LUA_GCSETPAUSELUA_GCSETSTEPMULLUA_GCINC

9 – Lua 的完整语法

以下是扩展 BNF 中 Lua 的完整语法。 像往常一样,在扩展 BNF 中, {A} 表示 0 或更多 As, [A] 表示可选的 A。 (有关运算符优先级,请参阅 §3.4.8; 有关终端的描述 名称、数字、 和文字字符串,请参阅 §3.1。

	chunk ::= block

	block ::= {stat} [retstat]

	stat ::=  ‘;’ | 
		 varlist ‘=’ explist | 
		 functioncall | 
		 label | 
		 break | 
		 goto Name | 
		 do block end | 
		 while exp do block end | 
		 repeat block until exp | 
		 if exp then block {elseif exp then block} [else block] end | 
		 for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 
		 for namelist in explist do block end | 
		 function funcname funcbody | 
		 local function Name funcbody | 
		 local attnamelist [‘=’ explist] 

	attnamelist ::=  Name attrib {‘,’ Name attrib}

	attrib ::= [‘<’ Name ‘>’]

	retstat ::= return [explist] [‘;’]

	label ::= ‘::’ Name ‘::’

	funcname ::= Name {‘.’ Name} [‘:’ Name]

	varlist ::= var {‘,’ var}

	var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 

	namelist ::= Name {‘,’ Name}

	explist ::= exp {‘,’ exp}

	exp ::=  nil | false | true | Numeral | LiteralString | ‘...’ | functiondef | 
		 prefixexp | tableconstructor | exp binop exp | unop exp 

	prefixexp ::= var | functioncall | ‘(’ exp ‘)’

	functioncall ::=  prefixexp args | prefixexp ‘:’ Name args 

	args ::=  ‘(’ [explist] ‘)’ | tableconstructor | LiteralString 

	functiondef ::= function funcbody

	funcbody ::= ‘(’ [parlist] ‘)’ block end

	parlist ::= namelist [‘,’ ‘...’] | ‘...’

	tableconstructor ::= ‘{’ [fieldlist] ‘}’

	fieldlist ::= field {fieldsep field} [fieldsep]

	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp

	fieldsep ::= ‘,’ | ‘;’

	binop ::=  ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ | 
		 ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ | 
		 ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 
		 and | or

	unop ::= ‘-’ | not | ‘#’ | ‘~

最后更新: 2 年 20 月 09 日星期二 38:2023:<> utc

你可能感兴趣的:(lua5.4)