创建二进制扩展模块

lua-users home
wiki

警告:此页面专门针对在 Windows 下使用 Borland 编译器构建 Lua 5.0 C 扩展库。此页面可能应该合并到更通用的页面 BuildingModules 中,并更新到 Lua 5.0。VersionNotice:此页面的一部分已过时(未使用 Require)。5.1. 将 loadlib 重命名为 package.loadlib。

描述

Lua 5.0 引入了 'loadlib' 函数,它允许 Lua 在运行时加载二进制扩展(实现是特定于平台的)。本文档展示了一个扩展模块的简单示例,并展示了如何在 Windows 下构建 Lua 以用于扩展模块。

示例

在 Windows 下,'loadlib' 是根据 DLL(动态链接库)实现的。以下是一个提供名为 'msgbox' 的 Lua 函数的扩展 DLL 的完整源代码

msgbox.c

  #include <windows.h>
  #include "lauxlib.h"
  
  /* Pop-up a Windows message box with your choice of message and caption */
  int lua_msgbox(lua_State* L)
  {
    const char* message = luaL_checkstring(L, 1);
    const char* caption = luaL_optstring(L, 2, "");
    int result = MessageBox(NULL, message, caption, MB_OK);
    lua_pushnumber(L, result);
    return 1;
  }

  int __declspec(dllexport) libinit (lua_State* L)
  {
   lua_register(L, "msgbox",  lua_msgbox);
   return 0;
  }

在将其构建到 Windows DLL(msgbox.dll)中后,您可以在 Lua 脚本中像这样使用它(省略了错误检查)

  libinit = loadlib("msgbox.dll", "_libinit")
  libinit()
  msgbox("Hey, it worked!", "Lua Message Box")

它使在运行时向支持 Lua-5.0 的应用程序添加扩展变得容易——无需重新构建甚至重新启动应用程序——这是一个非常方便的功能。但是,我忽略了一个重要的细节。

在构建扩展时,链接器必须解析 Lua/Luax API 函数(如 'lua_pushnumber' 或 'luaL_checkstring')的地址。如果这些函数存在于宿主应用程序(如 lua.exe)中,我们无法链接扩展模块。我们必须将 Lua API 移动到 DLL 中,以便宿主应用程序和扩展 DLL 可以共享相同的 Lua API 代码副本。

[* 更正:在 Windows 下,可以从 exe 文件导出函数,就像它是一个 dll 一样。因此,您可以从 lua.exe 导出函数(使用以下说明)并使用生成的导出库链接到新的 DLL *]

[* 如何?以下说明不起作用。在原型中使用 __declspec(dllexport) 不会导致这些函数从可执行文件中导出。我该怎么办? *]

[* 在 Windows 下,您不会从 exe 文件导出。虽然从技术上讲这是可能的,因为它们具有相同的格式,但您永远不会以这种方式设计 Windows 应用程序。将 lua 放入 DLL 中,设置 -DLUA_API=__declspec(dllexport),然后将生成的 lib 链接到您的 exe 和其他 DLL(如本页面所述),是正确的方法。顺便说一句,您可以*使用 implib 在 exe 文件上获取 .lib 文件,然后像使用普通 .lib 文件一样使用它们。 *]

将 Lua API 放入 DLL

这些说明适用于 Borland 的出色(且免费)Windows 命令行 ANSI C|C++ 编译器 [在此下载]

从 Lua 发行版的根目录开始

lua-5.0.2> bcc32 -elua.dll -WD -Iinclude;C:\Program\borland\Include -LC:\Program\borland\lib -DLUA_API=__declspec(dllexport) src\*.c src\lib\*.c
lua-5.0.2> implib lua lua.dll

这将提供给我们 lua.dll,其中包含 Lua API 和标准库;以及 lua.lib,一个导入库,我们可以将其静态链接到其他应用程序,以通过 lua.dll 为它们提供对 Lua API 的访问权限。

注意:__declspec(dllexport) 是 Microsoft 语言扩展(Borland 支持),它简化了 DLL 的创建和使用。它消除了提供“模块定义文件”的需要,该文件显式枚举了我们的 DLL 导出的每个函数。LUA_API 宏使我们有机会将 __declspec(dllexport) 插入到每个 Lua API 函数的函数原型中,自动将它们从生成的 DLL 中导出。

构建宿主应用程序

例如,要构建 lua.exe(在 Lua 发行版中)的版本,以便它使用 lua.dll,我们可以这样说(从发行版的根目录开始)

bcc32 -elua.exe -Iinclude -DLUA_API=__declspec(dllimport) lua.lib src\lua\*.c

注意,我们将 LUA_API 更改为 '__declspec(dllimport)',并将 lua.lib 链接进来。现在 lua.exe 将在运行时从 lua.dll 动态链接 Lua API 代码。

构建扩展 DLL

假设 msgbox.c(上面)是 Lua 发行版的根目录

bcc32 -w -tWD -Iinclude -DLUA_API=__declspec(dllimport) lua.lib msgbox.c

同样,我们将 LUA_API 设置为 '__declspec(dllimport)' 并链接 lua.lib。就这样。现在我们有了 msgbox.dll,一个可与 'loadlib' 一起使用的二进制扩展。

总结

构建二进制扩展并使用 loadlib 很容易,但我们必须确保 Lua API 在它自己的 DLL 中,以便宿主应用程序和任何扩展模块都可以共享它。


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2020 年 6 月 5 日下午 11:05 GMT (差异)