Lua Proxy Dll 四 |
|
缺點是
目前相依性略為混雜。我希望可以逐步改善。目前需要
pexports
(可以從 MSVC 使用 DUMPBIN /EXPORTS
,但要剖析輸出的話難度較高)。__declspec(naked)
只有 MSVC 支援)。我正在努力在 Mingw 中找出等效的內容,以期能採用全 Mingw 的方法。請注意,此解決方案不適用於搭載 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?