企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 5 – 辅助库 _辅助库_ 提供了一些便捷函数,方便在 C 中为 Lua 编程。 基础 API 提供了 C 和 Lua 交互用的主要函数, 而辅助库则为一些常见的任务提供了高阶函数。 所有辅助库中的函数和类型都定义在头文件 `lauxlib.h` 中, 它们均带有前缀 `luaL_`。 辅助库中的所有函数都基于基础 API 实现。 故而它们并没有提供任何基础 API 实现不了的功能。 虽然如此,使用辅助库可以让你的代码更为健壮。 一些辅助库函数会在内部使用一些额外的栈空间。 当辅助库使用的栈空间少于五个时, 它们不去检查栈大小;而是简单的假设栈够用。 一些辅助库中的函数用于检查 C 函数的参数。 因为错误信息格式化为指代参数 (例如,"`bad argument #1`"), 你就不要把这些函数用于参数之外的值了。 如果检查无法通过, `luaL_check*` 这些函数一定会抛出错误。 ## 5.1 – 函数和类型 这里我们按字母表次序列出了辅助库中的所有函数和类型。 ### `luaL_addchar` [-?, +?, _e_] ``` void luaL_addchar (luaL_Buffer *B, char c); ``` 向缓存 `B` (参见 [`luaL_Buffer`](#luaL_Buffer) ) 添加一个字节 `c`。 ### `luaL_addlstring` [-?, +?, _e_] ``` void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); ``` 向缓存 `B` (参见 [`luaL_Buffer`](#luaL_Buffer) ) 添加一个长度为 `l` 的字符串 `s`。 这个字符串可以包含零。 ### `luaL_addsize` [-?, +?, _e_] ``` void luaL_addsize (luaL_Buffer *B, size_t n); ``` 向缓存 `B` (参见 [`luaL_Buffer`](#luaL_Buffer) ) 添加一个已在之前复制到缓冲区(参见 [`luaL_prepbuffer`](#luaL_prepbuffer)) 的长度为 `n` 的字符串。 ### `luaL_addstring` [-?, +?, _e_] ``` void luaL_addstring (luaL_Buffer *B, const char *s); ``` 向缓存 `B` (参见 [`luaL_Buffer`](#luaL_Buffer) ) 添加一个零结尾的字符串 `s`。 ### `luaL_addvalue` [-1, +?, _e_] ``` void luaL_addvalue (luaL_Buffer *B); ``` 向缓存 `B` (参见 [`luaL_Buffer`](#luaL_Buffer) ) 添加栈顶的一个值,随后将其弹出。 这个函数是操作字符串缓存的函数中,唯一一个会(且必须)在栈上放置额外元素的。 这个元素将被加入缓存。 ### `luaL_argcheck` [-0, +0, _v_] ``` void luaL_argcheck (lua_State *L, int cond, int arg, const char *extramsg); ``` 检查 `cond` 是否为真。 如果不为真,以标准信息形式抛出一个错误 (参见 [`luaL_argerror`](#luaL_argerror))。 ### `luaL_argerror` [-0, +0, _v_] ``` int luaL_argerror (lua_State *L, int arg, const char *extramsg); ``` 抛出一个错误报告调用的 C 函数的第 `arg` 个参数的问题。 它使用下列标准信息并包含了一段 `extramsg` 作为注解: ``` bad argument #_arg_ to '_funcname_' (_extramsg_) ``` 这个函数永远不会返回。 ### `luaL_Buffer` ``` typedef struct luaL_Buffer luaL_Buffer; ``` _字符串缓存_ 的类型。 字符串缓存可以让 C 代码分段构造一个 Lua 字符串。 使用模式如下: * 首先定义一个类型为 [`luaL_Buffer`](#luaL_Buffer) 的变量 `b`。 * 调用 `luaL_buffinit(L, &b)` 初始化它。 * 然后调用 `luaL_add*` 这组函数向其添加字符串片断。 * 最后调用 `luaL_pushresult(&b)` 。 最后这次调用会在栈顶留下最终的字符串。 如果你预先知道结果串的长度, 你可以这样使用缓存: * 首先定义一个类型为 [`luaL_Buffer`](#luaL_Buffer) 的变量 `b`。 * 然后调用 `luaL_buffinitsize(L, &b, sz)` 预分配 `sz` 大小的空间。 * 接着将字符串复制入这个空间。 * 最后调用 `luaL_pushresultsize(&b, sz)`, 这里的 `sz` 指已经复制到缓存内的字符串长度。 一般的操作过程中,字符串缓存会使用不定量的栈槽。 因此,在使用缓存中,你不能假定目前栈顶在哪。 在对缓存操作的函数调用间,你都可以使用栈,只需要保证栈平衡即可; 即,在你做一次缓存操作调用时,当时的栈位置和上次调用缓存操作后的位置相同。 (对于 [`luaL_addvalue`](#luaL_addvalue) 是个唯一的例外。) 在调用完 [`luaL_pushresult`](#luaL_pushresult) 后, 栈会恢复到缓存初始化时的位置上,并在顶部压入最终的字符串。 ### `luaL_buffinit` [-0, +0, –] ``` void luaL_buffinit (lua_State *L, luaL_Buffer *B); ``` 初始化缓存 `B`。 这个函数不会分配任何空间; 缓存必须以一个变量的形式声明 (参见 [`luaL_Buffer`](#luaL_Buffer))。 ### `luaL_buffinitsize` [-?, +?, _e_] ``` char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz); ``` 等价于调用序列 [`luaL_buffinit`](#luaL_buffinit), [`luaL_prepbuffsize`](#luaL_prepbuffsize)。 ### `luaL_callmeta` [-0, +(0|1), _e_] ``` int luaL_callmeta (lua_State *L, int obj, const char *e); ``` 调用一个元方法。 如果在索引 `obj` 处的对象有元表, 且元表有域 `e` 。 这个函数会以该对象为参数调用这个域。 这种情况下,函数返回真并将调用返回值压栈。 如果那个位置没有元表,或没有对应的元方法, 此函数返回假(并不会将任何东西压栈)。 ### `luaL_checkany` [-0, +0, _v_] ``` void luaL_checkany (lua_State *L, int arg); ``` 检查函数在 `arg` 位置是否有任何类型(包括 **nil**)的参数。 ### `luaL_checkinteger` [-0, +0, _v_] ``` lua_Integer luaL_checkinteger (lua_State *L, int arg); ``` 检查函数的第 `arg` 个参数是否是一个 整数(或是可以被转换为一个整数) 并以 [`lua_Integer`](#lua_Integer) 类型返回这个整数值。 ### `luaL_checklstring` [-0, +0, _v_] ``` const char *luaL_checklstring (lua_State *L, int arg, size_t *l); ``` 检查函数的第 `arg` 个参数是否是一个 字符串,并返回该字符串; 如果 `l` 不为 `NULL` , 将字符串的长度填入 `*l`。 这个函数使用 [`lua_tolstring`](#lua_tolstring) 来获取结果。 所以该函数有可能引发的转换都同样有效。 ### `luaL_checknumber` [-0, +0, _v_] ``` lua_Number luaL_checknumber (lua_State *L, int arg); ``` 检查函数的第 `arg` 个参数是否是一个 数字,并返回这个数字。 ### `luaL_checkoption` [-0, +0, _v_] ``` int luaL_checkoption (lua_State *L, int arg, const char *def, const char *const lst[]); ``` 检查函数的第 `arg` 个参数是否是一个 字符串,并在数组 `lst` (比如是零结尾的字符串数组) 中查找这个字符串。 返回匹配到的字符串在数组中的索引号。 如果参数不是字符串,或是字符串在数组中匹配不到,都将抛出错误。 如果 `def` 不为 `NULL`, 函数就把 `def` 当作默认值。 默认值在参数 `arg` 不存在,或该参数是 **nil** 时生效。 这个函数通常用于将字符串映射为 C 枚举量。 (在 Lua 库中做这个转换可以让其使用字符串,而不是数字来做一些选项。) ### `luaL_checkstack` [-0, +0, _v_] ``` void luaL_checkstack (lua_State *L, int sz, const char *msg); ``` 将栈空间扩展到 `top + sz` 个元素。 如果扩展不了,则抛出一个错误。 `msg` 是用于错误消息的额外文本 (`NULL` 表示不需要额外文本)。 ### `luaL_checkstring` [-0, +0, _v_] ``` const char *luaL_checkstring (lua_State *L, int arg); ``` 检查函数的第 `arg` 个参数是否是一个 字符串并返回这个字符串。 这个函数使用 [`lua_tolstring`](#lua_tolstring) 来获取结果。 所以该函数有可能引发的转换都同样有效。 ### `luaL_checktype` [-0, +0, _v_] ``` void luaL_checktype (lua_State *L, int arg, int t); ``` 检查函数的第 `arg` 个参数的类型是否是 `t`。 参见 [`lua_type`](#lua_type) 查阅类型 `t` 的编码。 ### `luaL_checkudata` [-0, +0, _v_] ``` void *luaL_checkudata (lua_State *L, int arg, const char *tname); ``` 检查函数的第 `arg` 个参数是否是一个类型为 `tname` 的用户数据 (参见 [`luaL_newmetatable`](#luaL_newmetatable) )。 它会返回该用户数据的地址 (参见 [`lua_touserdata`](#lua_touserdata))。 ### `luaL_checkversion` [-0, +0, –] ``` void luaL_checkversion (lua_State *L); ``` 检查调用它的内核是否是创建这个 Lua 状态机的内核。 以及调用它的代码是否使用了相同的 Lua 版本。 同时也检查调用它的内核与创建该 Lua 状态机的内核 是否使用了同一片地址空间。 ### `luaL_dofile` [-0, +?, _e_] ``` int luaL_dofile (lua_State *L, const char *filename); ``` 加载并运行指定的文件。 它是用下列宏定义出来: ``` (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0)) ``` 如果没有错误,函数返回假; 有错则返回真。 ### `luaL_dostring` [-0, +?, –] ``` int luaL_dostring (lua_State *L, const char *str); ``` 加载并运行指定的字符串。 它是用下列宏定义出来: ``` (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0)) ``` 如果没有错误,函数返回假; 有错则返回真。 ### `luaL_error` [-0, +0, _v_] ``` int luaL_error (lua_State *L, const char *fmt, ...); ``` 抛出一个错误。 错误消息的格式由 `fmt` 给出。 后面需提供若干参数, 这些参数遵循 [`lua_pushfstring`](#lua_pushfstring) 中的规则。 如果能获得相关信息,它还会在消息前面加上错误发生时的文件名及行号。 这个函数永远不会返回。 但是在 C 函数中通常遵循惯用法: `return luaL_error(_args_)` 。 ### `luaL_execresult` [-0, +3, _e_] ``` int luaL_execresult (lua_State *L, int stat); ``` 这个函数用于生成标准库中和进程相关函数的返回值。 (指 [`os.execute`](#pdf-os.execute) 和 [`io.close`](#pdf-io.close))。 ### `luaL_fileresult` [-0, +(1|3), _e_] ``` int luaL_fileresult (lua_State *L, int stat, const char *fname); ``` 这个函数用于生成标准库中和文件相关的函数的返回值。 (指 ([`io.open`](#pdf-io.open), [`os.rename`](#pdf-os.rename), [`file:seek`](#pdf-file:seek),等。)。 ### `luaL_getmetafield` [-0, +(0|1), _e_] ``` int luaL_getmetafield (lua_State *L, int obj, const char *e); ``` 将索引 `obj` 处对象的元表中 `e` 域的值压栈。 如果该对象没有元表,或是该元表没有相关域, 此函数什么也不会压栈并返回 `LUA_TNIL`。 ### `luaL_getmetatable` [-0, +1, –] ``` int luaL_getmetatable (lua_State *L, const char *tname); ``` 将注册表中 `tname` 对应的元表 (参见 [`luaL_newmetatable`](#luaL_newmetatable))压栈。 如果没有 `tname` 对应的元表,则将 **nil** 压栈并返回假。 ### `luaL_getsubtable` [-0, +1, _e_] ``` int luaL_getsubtable (lua_State *L, int idx, const char *fname); ``` 确保 `t[fname]` 是一张表,并将这张表压栈。 这里的 `t` 指索引 `idx` 处的值。 如果它原来就是一张表,返回真; 否则为它创建一张新表,返回假。 ### `luaL_gsub` [-0, +1, _e_] ``` const char *luaL_gsub (lua_State *L, const char *s, const char *p, const char *r); ``` 将字符串 `s` 生成一个副本, 并将其中的所有字符串 `p` 都替换为字符串 `r` 。 将结果串压栈并返回它。 ### `luaL_len` [-0, +0, _e_] ``` lua_Integer luaL_len (lua_State *L, int index); ``` 以数字形式返回给定索引处值的“长度”; 它等价于在 Lua 中调用 '`#`' 的操作 (参见 [§3.4.7](#3.4.7))。 如果操作结果不是一个整数,则抛出一个错误。 (这种情况只发生在触发元方法时。) ### `luaL_loadbuffer` [-0, +1, –] ``` int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, const char *name); ``` 等价于 [`luaL_loadbufferx`](#luaL_loadbufferx), 其 `mode` 参数等于 `NULL`。 ### `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`](#lua_load) 来加载 `buff` 指向的长度为 `sz` 的内存区。 这个函数和 [`lua_load`](#lua_load) 返回值相同。 `name` 作为代码块的名字,用于调试信息和错误消息。 `mode` 字符串的作用同函数 [`lua_load`](#lua_load)。 ### `luaL_loadfile` [-0, +1, _e_] ``` int luaL_loadfile (lua_State *L, const char *filename); ``` 等价于 [`luaL_loadfilex`](#luaL_loadfilex), 其 `mode` 参数等于 `NULL`。 ### `luaL_loadfilex` [-0, +1, _e_] ``` int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); ``` 把一个文件加载为 Lua 代码块。 这个函数使用 [`lua_load`](#lua_load) 加载文件中的数据。 代码块的名字被命名为 `filename`。 如果 `filename` 为 `NULL`, 它从标准输入加载。 如果文件的第一行以 `#` 打头,则忽略这一行。 `mode` 字符串的作用同函数 [`lua_load`](#lua_load)。 此函数的返回值和 [`lua_load`](#lua_load) 相同, 不过它还可能产生一个叫做 `LUA_ERRFILE` 的出错码。这种错误发生于无法打开或读入文件时,或是文件的模式错误。 和 [`lua_load`](#lua_load) 一样,这个函数仅加载代码块不运行。 ### `luaL_loadstring` [-0, +1, –] ``` int luaL_loadstring (lua_State *L, const char *s); ``` 将一个字符串加载为 Lua 代码块。 这个函数使用 [`lua_load`](#lua_load) 加载一个零结尾的字符串 `s`。 此函数的返回值和 [`lua_load`](#lua_load) 相同。 也和 [`lua_load`](#lua_load) 一样,这个函数仅加载代码块不运行。 ### `luaL_newlib` [-0, +1, _e_] ``` 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, _e_] ``` void luaL_newlibtable (lua_State *L, const luaL_Reg l[]); ``` 创建一张新的表,并预分配足够保存下数组 `l` 内容的空间(但不填充)。 这是给 [`luaL_setfuncs`](#luaL_setfuncs) 一起用的 (参见 [`luaL_newlib`](#luaL_newlib))。 它以宏形式实现, 数组 `l` 必须是一个数组,而不能是一个指针。 ### `luaL_newmetatable` [-0, +1, _e_] ``` int luaL_newmetatable (lua_State *L, const char *tname); ``` 如果注册表中已存在键 `tname`,返回 0 。 否则, 为用户数据的元表创建一张新表。 向这张表加入 `__name = tname` 键值对, 并将 `[tname] = new table` 添加到注册表中, 返回 1 。 (`__name`项可用于一些错误输出函数。) 这两种情况都会把最终的注册表中关联 `tname` 的值压栈。 ### `luaL_newstate` [-0, +0, –] ``` lua_State *luaL_newstate (void); ``` 创建一个新的 Lua 状态机。 它以一个基于标准 C 的 `realloc` 函数实现的内存分配器 调用 [`lua_newstate`](#lua_newstate) 。 并把可打印一些出错信息到标准错误输出的 panic 函数(参见 [§4.6](#4.6)) 设置好,用于处理致命错误。 返回新的状态机。 如果内存分配失败,则返回 `NULL` 。 ### `luaL_openlibs` [-0, +0, _e_] ``` void luaL_openlibs (lua_State *L); ``` 打开指定状态机中的所有 Lua 标准库。 ### `luaL_optinteger` [-0, +0, _v_] ``` lua_Integer luaL_optinteger (lua_State *L, int arg, lua_Integer d); ``` 如果函数的第 `arg` 个参数是一个 整数(或可以转换为一个整数), 返回该整数。 若该参数不存在或是 **nil**, 返回 `d`。 除此之外的情况,抛出错误。 ### `luaL_optlstring` [-0, +0, _v_] ``` const char *luaL_optlstring (lua_State *L, int arg, const char *d, size_t *l); ``` 如果函数的第 `arg` 个参数是一个 字符串,返回该字符串。 若该参数不存在或是 **nil**, 返回 `d`。 除此之外的情况,抛出错误。 若 `l` 不为 `NULL`, 将结果的长度填入 `*l` 。 ### `luaL_optnumber` [-0, +0, _v_] ``` lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d); ``` 如果函数的第 `arg` 个参数是一个 数字,返回该数字。 若该参数不存在或是 **nil**, 返回 `d`。 除此之外的情况,抛出错误。 ### `luaL_optstring` [-0, +0, _v_] ``` const char *luaL_optstring (lua_State *L, int arg, const char *d); ``` 如果函数的第 `arg` 个参数是一个 字符串,返回该字符串。 若该参数不存在或是 **nil**, 返回 `d`。 除此之外的情况,抛出错误。 ### `luaL_prepbuffer` [-?, +?, _e_] ``` char *luaL_prepbuffer (luaL_Buffer *B); ``` 等价于 [`luaL_prepbuffsize`](#luaL_prepbuffsize), 其预定义大小为 `LUAL_BUFFERSIZE`。 ### `luaL_prepbuffsize` [-?, +?, _e_] ``` char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz); ``` 返回一段大小为 `sz` 的空间地址。 你可以将字符串复制其中以加到缓存 `B` 内 (参见 [`luaL_Buffer`](#luaL_Buffer))。 将字符串复制其中后,你必须调用 [`luaL_addsize`](#luaL_addsize) 传入字符串的大小,才会真正把它加入缓存。 ### `luaL_pushresult` [-?, +1, _e_] ``` void luaL_pushresult (luaL_Buffer *B); ``` 结束对缓存 `B` 的使用,将最终的字符串留在栈顶。 ### `luaL_pushresultsize` [-?, +1, _e_] ``` void luaL_pushresultsize (luaL_Buffer *B, size_t sz); ``` 等价于 [`luaL_addsize`](#luaL_addsize),[`luaL_pushresult`](#luaL_pushresult)。 ### `luaL_ref` [-1, +0, _e_] ``` int luaL_ref (lua_State *L, int t); ``` 针对栈顶的对象,创建并返回一个在索引 `t` 指向的表中的 _引用_ (最后会弹出栈顶对象)。 此引用是一个唯一的整数键。 只要你不向表 `t` 手工添加整数键, [`luaL_ref`](#luaL_ref) 可以保证它返回的键的唯一性。 你可以通过调用 `lua_rawgeti(L, t, r)` 来找回由 `r` 引用的对象。 函数 [`luaL_unref`](#luaL_unref) 用来释放一个引用关联的对象 如果栈顶的对象是 **nil**, [`luaL_ref`](#luaL_ref) 将返回常量 `LUA_REFNIL`。 常量 `LUA_NOREF` 可以保证和 [`luaL_ref`](#luaL_ref) 能返回的其它引用值不同。 ### `luaL_Reg` ``` typedef struct luaL_Reg { const char *name; lua_CFunction func; } luaL_Reg; ``` 用于 [`luaL_setfuncs`](#luaL_setfuncs) 注册函数的数组类型。 `name` 指函数名,`func` 是函数指针。 任何 [`luaL_Reg`](#luaL_Reg) 数组必须以一对 `name` 与 `func` 皆为 `NULL` 结束。 ### `luaL_requiref` [-0, +1, _e_] ``` void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb); ``` 如果 `modname` 不在 [`package.loaded`](#pdf-package.loaded) 中, 则调用函数 `openf` ,并传入字符串 `modname`。 将其返回值置入 `package.loaded[modname]`。 这个行为好似该函数通过 [`require`](#pdf-require) 调用过一样。 如果 `glb` 为真, 同时也讲模块设到全局变量 `modname` 里。 在栈上留下该模块的副本。 ### `luaL_setfuncs` [-nup, +0, _e_] ``` void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); ``` 把数组 `l` 中的所有函数 (参见 [`luaL_Reg`](#luaL_Reg)) 注册到栈顶的表中(该表在可选的上值之下,见下面的解说)。 若 `nup` 不为零, 所有的函数都共享 `nup` 个上值。 这些值必须在调用之前,压在表之上。 这些值在注册完毕后都会从栈弹出。 ### `luaL_setmetatable` [-0, +0, –] ``` void luaL_setmetatable (lua_State *L, const char *tname); ``` 将注册表中 `tname` 关联元表 (参见 [`luaL_newmetatable`](#luaL_newmetatable)) 设为栈顶对象的元表。 ### `luaL_Stream` ``` typedef struct luaL_Stream { FILE *f; lua_CFunction closef; } luaL_Stream; ``` 标准输入输出库中用到的标准文件句柄结构。 文件句柄实现为一个完全用户数据, 其元表被称为 `LUA_FILEHANDLE` (`LUA_FILEHANDLE` 是一个代表真正元表的名字的宏)。 这张元表由标准输入输出库(参见 [`luaL_newmetatable`](#luaL_newmetatable))创建。 用户数据必须以结构 `luaL_Stream` 开头; 此结构其后可以包含任何其它数据。 `f` 域指向一个 C 数据流 (如果它为 `NULL` 表示一个没有创建好的句柄)。 `closef` 域指向一个在关闭或回收该流时需要调用的 Lua 函数。 该函数将收到一个参数,即文件句柄。 它需要返回 **true**(操作成功)或 **nil** 加错误消息(出错的时候)。 一旦 Lua 调用过这个域,该域的值就会修改为 `NULL` 以提示这个句柄已经被关闭了。 ### `luaL_testudata` [-0, +0, _e_] ``` void *luaL_testudata (lua_State *L, int arg, const char *tname); ``` 此函数和 [`luaL_checkudata`](#luaL_checkudata) 类似。 但它在测试失败时会返回 `NULL` 而不是抛出错误。 ### `luaL_tolstring` [-0, +1, _e_] ``` const char *luaL_tolstring (lua_State *L, int idx, size_t *len); ``` 将给定索引处的 Lua 值转换为一个相应格式的 C 字符串。 结果串不仅会压栈,还会由函数返回。 如果 `len` 不为 `NULL` , 它还把字符串长度设到 `*len` 中。 如果该值有一个带 `"__tostring"` 域的元表, `luaL_tolstring` 会以该值为参数去调用对应的元方法, 并将其返回值作为结果。 ### `luaL_traceback` [-0, +1, _e_] ``` void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); ``` 将栈 `L1` 的栈回溯信息压栈。 如果 `msg` 不为 `NULL` ,它会附加到栈回溯信息之前。 `level` 参数指明从第几层开始做栈回溯。 ### `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); ``` 释放索引 `t` 处表的 `ref` 引用对象 (参见 [`luaL_ref`](#luaL_ref) )。 此条目会从表中移除以让其引用的对象可被垃圾收集。 而引用 `ref` 也被回收再次使用。 如果 `ref` 为 [`LUA_NOREF`](#pdf-LUA_NOREF) 或 [`LUA_REFNIL`](#pdf-LUA_REFNIL), [`luaL_unref`](#luaL_unref) 什么也不做。 ### `luaL_where` [-0, +1, _e_] ``` void luaL_where (lua_State *L, int lvl); ``` 将一个用于表示 `lvl` 层栈的控制点位置的字符串压栈。 这个字符串遵循下面的格式: ``` _chunkname_:_currentline_: ``` 0 层指当前正在运行的函数, 1 层指调用正在运行函数的函数, 依次类推。 这个函数用于构建错误消息的前缀。