二進制模組教學

lua-users home
wiki

一種讓 Lua 擴充功能即載即用(非破壞性)的方法

版本公告:此頁面與早期版本的 Lua(4.0 及 5.0beta)有關,使用 loadmodule 擴充功能。Lua 5.1 使用 package.loadlibrequire。Lua 5.0 使用 loadlib。)

此頁面的目標在於展示如何輕鬆從現有的 Lua 擴充功能建立 LuaBinaryModules 而免於變更擴充功能的原始程式碼 - MartinSpernau

目標:將現有的 Lua 擴充功能(最初靜態連結至 Lua 可執行檔)編譯為動態連結庫,藉由在 LuaBinaryModules 中描述的 loadmodule() 功能在執行時期載入。

特別目標:不變更原始程式碼(它很有可能是其他人撰寫的)

討論:Lua 擴充功能通常由多個原始檔和標頭檔組成,這些檔可以實作想要的功。讓 Lua 詮譯器可以使用這些函數的方式是透過特殊的包裝器函數,以及一個「開放」函數,該函數會將這些函數「註冊」到當前的 Lua 狀態。(關於這方面的討論可以在 Lua 參考文件找到,或參閱 BindingCodeToLua

loadmodule 功能 (LuaBinaryModules) 利用了一個事實來運作:基本上每個擴充功能都只定義一個「開啟」函數。由於這些函數可以有特定於每個擴充功能的不同名稱(例如 lua_bitlibopen、lua_fooinizialize 等),loadmodule 模組會將庫開啟程式碼包裝到一個已定義的函數 luaLM_import 中。它也會定義 luaLM_version,這是檢查擴充功能與核心 Lua 函式庫的版本相容性所需要的函數。

現在這兩個函數會作為此動態連結庫要編譯的唯一外部進入點。當從 Lua 呼叫 loadmodule('modname') 時,它會嘗試為該擴充功能載入 dll(在 Windows 上它會是 luamodname.dll)。接著它會呼叫 luaLM_version 來檢查版本,如果一切都正常就會呼叫 luaLM_import,然後進一步初始化函數的實際註冊。

將現有的擴充功能移植為可啟用 loadmodule 的 dll 一般來說,為擴充功能新增兩個必要的 luaLM 函數,並將其編譯為動態連結庫就已經足夠了。這通常會透過撰寫一個宣告這兩個函數的簡單 .def 檔案來執行。

待辦:新增在常見編譯器中執行的說明

作者希望介紹一種稍有不同的方法,這個方法的優點是無須變更原始程式碼。

ReubenThomas 中的 bitlib 將會在此作為範例,因為它本身很小,也沒有外部相依性。以下說明的步驟可用於大多數其他擴充功能。Bitlib 提供位元邏輯運算

需要什麼

#include "lua.h"
extern void lua_bitlibopen (lua_State *L);

/* special functions for use with loadmodule.c */
int luaLM_import( lua_State *L )
{
 lua_bitlibopen(L);
 return 0;
}

const char * luaLM_version( void )
{
	return LUA_VERSION;
}
;  luabitlib.def: Declares the module parameters for the DLL.

LIBRARY      luabitlib
DESCRIPTION  'Lua bitwise operations library'

EXPORTS
    ; Explicit exports can go here
	luaLM_version	@1
	luaLM_import	@2        

現在可以將 luabitlib.dll 放到 Lua (已啟用 loadlib) 可存取的路徑中 (放到同一個資料夾也可以),並載入到像這樣的程式碼中

>loadmodule("bitlib")
using bitlib
>a=5
>b=2
>print(imod(a,b))     -- returns the integer remainder of a divided by b
1

可以在 [這裡] 下載完整的來源和 VC 專案檔

注意:還有另一種方便的方法可以建立函式庫。如果您已經有 .lib 檔案,您只要建立一個空的 dll 專案,其中包含該 lib、代理程式檔和 def 檔案,將它們組合在一起並建立,這樣就完成了。


最近的變更 · 偏好設定
編輯 · 歷史紀錄
最後編輯於 2007 年 1 月 14 日,上午 1:56 GMT (diff)