Lua Proxy Dll 四

lua-users home
wiki

以下是另一個針對 Lua 的代理 DLL 食譜。特別在於允許靜態連結的 Lua 安全地載入外部模組。這個版本的幾個用途是其他版本所沒有的

缺點是

目前相依性略為混雜。我希望可以逐步改善。目前需要

請注意,此解決方案不適用於搭載 x64 的 MSVC,這是因為 x64 編譯器不支援「naked」屬性及 __asm 指令。

makeproxy.lua:

local CFILE = "luaproxy.c" -- Name of the C file for the proxy DLL
local SYMBOLS = "luasymbols.h" -- Name of the file of Lua symbols
local LUADLL = "lua51.dll" -- Name of a real Lua DLL (to get exported symbols)

----------------------------------------------------------------------
local cfile = assert(io.open(CFILE, "w"))
cfile:write [=[
#include <windows.h>

static struct {
#define SYMBOL(name) FARPROC name;
#include "luasymbols.h"
#undef SYMBOL
}
s_funcs;

/* Macro for defining a proxy function.
   This is a direct jump (single "jmp" assembly instruction"),
   preserving stack and return address.
   The following uses MSVC inline assembly which may not be
   portable with other compilers.
 */

#define SYMBOL(name) \
  void __declspec(dllexport,naked) name() { __asm { jmp s_funcs.name } }
#include "luasymbols.h"
#undef SYMBOL

BOOL APIENTRY
DllMain(HANDLE module, DWORD reason, LPVOID reserved)
{
    HANDLE h = GetModuleHandle(NULL);
#define SYMBOL(name) s_funcs.name = GetProcAddress(h, #name);
#include "luasymbols.h"
#undef SYMBOL
    return TRUE;
}
]=]
cfile:close()

symbols = io.popen("pexports "..LUADLL)
symfile = io.open(SYMBOLS, "w")
for sym in symbols:lines() do
    -- Skip the LIBRARY and EXPORTS lines
    start = sym:sub(1,3)
    if start ~= "LIB" and start ~= "EXP" then
	symfile:write("SYMBOL("..sym..")\n")
    end
end
symbols:close()
symfile:close()

os.execute(table.concat({
    "cl /O2 /LD /GS-",
     CFILE,
     "/link /out:lua51.dll /nodefaultlib /entry:DllMain kernel32.lib"}, " "))

要使用代理,只要讓建置好的 lua51.dll 在你的 PATH 中取用得到,而不用用標準的版本。靜態連結至 lua51.dll 的附加程式會找到它,並自動使用主程式中靜態 Lua 執行時期。當然,所有正常的 C 執行時期問題依然適用 - 主程式和任何動態載入的附加程式都應該使用相同的 CRT,否則可能會產生問題 (遺憾的是,C 不提供像 Lua 那樣的優雅代理解決方案,吼吼 :-))

-- PaulMoore?

另請參閱


RecentChanges · 偏好設定
編輯 · 歷史
最後編輯於 2019 年 11 月 15 日,下午 10:04 GMT (差異)