二進制模組教學 |
|
版本公告:此頁面與早期版本的 Lua(4.0 及 5.0beta)有關,使用 loadmodule
擴充功能。Lua 5.1 使用 package.loadlib
及 require
。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 檔案,將它們組合在一起並建立,這樣就完成了。