加载代码的本质 |
|
loadstring [1] 函数从指定的字符串(可以是编译后的 Lua 字节码,也可以是 loadstring 编译成 Lua 字节码的 Lua 源代码)实例化一个 Lua 函数。还有一些相关的函数。loadfile [2] 函数类似,但它从给定文件系统路径的文件中获取代码。loadstring 和 loadfile 都是基于更底层的 load 函数实现的更高级别的函数。load [3] 函数从零个或多个零散获取的子字符串的连接中实例化一个 Lua 函数。当代码很大且需要零散读取时(例如,文件分块读取),load 可能比 loadstring 更高效,因为它不一定将整个源代码字符串存储在内存中,而只存储字节码。
dofile [4] 的功能与 loadfile 相同,但还会执行该函数。
package.loadlib [5] 函数实例化一个 Lua 函数,该函数封装了指定动态加载的共享库 [6] 的指定符号名称的原生代码(相对路径以特定于操作系统的方式进行搜索 [6][7][8])。这尤其允许在运行时动态加载非 Lua 代码。
package.loaders [9] 是一个搜索器函数 [9] 的数组(也许它应该被命名为 package.searchers [15])。这些搜索器函数中的每一个都可以用来尝试从由传递给搜索器函数的包名 [10] 标识的某个位置实例化一个 Lua 函数。其中一个搜索器函数是基于 loadfile 实现的。另外两个是基于 package.loadlib 实现的。还有一个不使用它们,而是返回预先缓存在内存中的 Lua 函数。您也可以添加自己的搜索器(例如,从 ZIP 文件加载或从网上下载)。
包名到文件系统路径的映射仅适用于存储在文件系统中的代码块。这是通过 package.path [11] 和 package.cpath [12] 变量定义的。这个映射预计将在 LuaFiveTwo 中作为 package.searchpath 函数暴露出来。通常,包名不需要遵循约定格式(例如,它可以是 URL 或 GUID),只要某个搜索器能够理解它即可。
require [13] 函数返回 package.loaded [14] 表中以指定包名作为键缓存的值。如果该值不存在,它会通过依次调用 package.loaders 中的搜索器函数来获取模块的加载器函数,然后将包名作为参数传递给加载器函数来调用它,将返回值缓存在 package.loaded 中,并返回该值。
请注意,模块加载是加载函数的特例。可以使用 package.loaders 加载并非用于 Lua 模块的函数。require 函数也不一定需要使用 module 函数,即使是对于模块。
require 函数的基本操作,实现了一个自定义搜索器(libtcc),并指出了可以实现的各种其他搜索器。