建立二進位延伸模組

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 下,會以 DLL(動態連結函式庫)的形式實作「loadlib」。以下是提供一個稱為「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 中,才是正確的方法。順帶一提,*可以*對 exe 檔案使用 implib 來取得 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 中,讓主機應用程式及任何擴充模組都能夠共用。


RecentChanges · 喜好設定
編輯 · 歷程記錄
最後編輯時間為 2020 年 6 月 5 日,晚上 11:05 GMT (diff)