Lua 二进制模块 |
|
版本说明:本页面涉及较早版本的 Lua(4.0 和 5.0 beta),使用了 `loadmodule` 扩展。Lua 5.1 使用 `package.loadlib` 和 `require`。Lua 5.0 使用 `loadlib`。)
注意:LuaCheia 是 Lua 5.0 的一个可移植、维护良好的发行版,它包含并依赖于此处启动的 loadmodule 支持。
本页面包含一个应用于 Lua 4.0.1 的补丁,该补丁向默认的 Lua 解释器添加了一个 `loadmodule` 函数。本页面还列出了一些可以使用 `loadmodule` 加载的二进制模块。这些二进制模块可以在不重新编译任何代码的情况下,用原生代码扩展默认 Lua 解释器的功能。这使得最终用户非常容易访问有用的库,特别是库的组合,而这些组合否则需要为所需的平台重新编译源代码。
要使用本页面列出的二进制模块,需要一个修改过的解释器。源代码和二进制文件链接如下。这些代码主要由 IgnacioCastano 编写。 ThatcherUlrich 对其进行了少量修改。
要应用补丁:将正确的 Lua 发行版解压到一个干净的目录中。`cd` 到该目录的顶层并运行 patch。例如,假设您将 lua.tar.gz 和上面的补丁文件保存在 ~/src
cd ~/src
tar -xzvf lua.tar.gz
mv lua-4.0.1 lua-4.0.1-loadmodule
cd lua-4.0.1-loadmodule
patch -p1 < ../lua-4.0-loadmodule-2002-11-21.patch
在构建之前,请务必查看 `config` 文件,以确保为您的平台设置了选项。
下面的二进制文件是使用标准的 Lua 4.0.1 发行版编译的,并添加了上述补丁。直接下载并使用即可。
[GNU/Linux-i386] | [Win32] | Mac | *BSD | Solaris
在您的 Lua 脚本中,执行
loadmodule("modulename")
这将动态加载模块中的代码,并初始化与 Lua 的绑定。有关如何从 Lua 使用它的详细信息,请参阅每个模块的文档。
loadmodule 函数返回两个值。一个布尔值,用于确定 loadmodule 是否成功;一个字符串,用于描述库(如果成功)或描述错误(如果失败)。
ok, str = loadmodule "modulename" if not ok then error( str ) else print( "using " .. str ) end
或者,在大多数情况下,您会这样做
assert( loadmodule "modulename" )
如果 modulename 不存在,它将打印
假定 Lua 库的前缀是 'lua',以区分包装库与其被包装的对应项。所以,当您执行
loadmodule("SDL")
您正在加载 `luaSDL` 库。此外,每个平台都有自己的命名方式。目前,loadmodule 在 Win32 和支持 DLFCN 的系统(Linux、OSX 和大多数 UNIX 类型)下受支持。
例如,在 Win32 上,库的扩展名为 '.dll',所以 `luaSDL` 的库名称将是
luaSDL.dll
而在 Linux 系统上,它将是
libluaSDL.so
但是,在您的 lua 脚本中,您不必关心系统约定,只需执行:`loadmodule("SDL")`。
库搜索路径是系统依赖的。
Linux 按以下顺序搜索库
SunOs? 按以下顺序搜索库
Windows 按以下顺序搜索库
此外,luamodule 在预定义的搜索路径之前会查找自定义路径中的模块。该路径由全局键 LUA_LIBPATH 设置。如果键不存在,则会在 LUA_LIBPATH 环境变量中查找自定义路径。这应该允许您使用比系统上安装的版本更新的库。
Lua 二进制模块是一个特定于平台的共享库(例如,在大多数 Unix 系统上是 .so,在 Win32 上是 .DLL),它导出这两个特殊函数
const char* luaLM_version(void);
int luaLM_import(lua_State* L);
函数 `luaLM_version()` 应返回编译模块时使用的 LUA_VERSION 的值;例如,在您的源代码中通常应如下所示
const char* luaLM_version(void)
{
return LUA_VERSION;
}
`loadmodule` 首先调用此函数,以确保二进制模块与正在加载它的 Lua 解释器兼容。
函数 `luaLM_import(lua_State* L)` 是 `loadmodule` 调用以实现您的绑定的函数。在这里,您可以使用常规的 Lua API 将模块的函数和变量绑定到给定的 `lua_State`。
强烈建议您将所有绑定放入一个*命名空间*中。也就是说,您绑定到 Lua 的所有函数和值都应包含在一个表中。有关 Lua 命名空间的解释,请参阅 LTN7 [1]。建议该表的名称对应于您的模块名称。例如,由 `loadmodule("SDL")` 加载的 `luaSDL` 模块将其所有绑定都放在一个名为“SDL”的表中。用户可以根据需要为该表分配不同的名称,以便于使用。
注意:`loadmodule` 不强制使用命名空间。但如果坚持使用,您的用户可能会更满意。
待办:解释模块中的静态状态为什么危险
待办:关于 tolua 的建议和示例
模块作者:将您的模块添加到下面的列表中,并附有简短的描述。包括一个指向 wiki 或网页的链接,用户可以在其中获得模块的完整描述,并下载模块的二进制文件(以及源代码,如果可用)。
以下是可以与上述解释器一起使用的二进制模块列表。(许多这些模块也可以通过为您的平台编译源代码并与您自己的自定义解释器静态链接,以更传统的方式集成到 Lua 中。)
我更新了源代码补丁:添加了一些 Makefile 更改,以更好地支持 Linux .so。现在 .so 和可执行文件都附加了 $(V)(所以解释器是 `lua-4.0`,主库是 `liblua-4.0.so`)。此外,还有新的二进制文件,一个包含可执行文件和 .so 的 tarball。 - ThatcherUlrich
Thatcher:补丁中有一些错误,如果您更改了静态库的名称,您还需要更改 src/Makefile 和 src/lib/Makefile 中的目标。您还删除了 .def 文件。您实际上可以通过注释 Makefile 中的一行并重新定义 LUA_API 和 LUALIB_API 来生成它们,但我认为直接使用提供的 .def 文件而不做任何更改会更容易。如果其他人也遇到新补丁的问题,以前的补丁仍然在这里:[patch]。 - IgnacioCastano
我上传了一个 [zip],其中包含我当前 lua-loadmodule 树的所有源代码和项目文件。 -MartinSpernau
我修改了 loadmodule,使其在检查版本时忽略修订号。这是新的 [patch]。如果没有人报告任何错误,我将在几天内更新上面的链接。 - IgnacioCastano
这里有一个适用于 lua-5.0-beta 的新补丁:[patch]。它尚未完全测试,请谨慎使用。 - IgnacioCastano
对 lua-5 的 loadmodule 添加非常棒;我正在使用它来创建一个 lua-5 LuaSqlite 可加载二进制模块。但是,如果其语义与 [Import (TN11)] 完全相同,那岂不是更好?这将使模块对全局命名空间的依赖性降低。
说实话,我认为 LTN11 引入的复杂性是为了解决实际上不是问题的问题。事实是,模块需要唯一的名称,所以我认为直接解决名称冲突并坚持 LTN7 的约定更不容易混淆。 -ThatcherUlrich
恕我直言,我认为 LTN11 引入的复杂性很小(如果不是没有的话),并且解决了几个问题——尽管它们可能不是所有人的问题。例如,它允许同时使用同一个接口的两个实现(如果你愿意,就是同一个模块的两个版本),这对于测试非常方便。它还使模块沙盒化更加实用,并且开启了拥有具有内部状态的模块(如 readline 或 Lua 本身)的多个实例的可能性。从 C 的角度来看,“额外的复杂性”仅仅是模块打开函数使用一个作为参数的表,而不是直接将其添加到全局命名空间;该表本身由包系统提供。 -RiciLake