Lua Proxy Dll Four |
|
require()
external modules. This version serves a couple of purposes which are not covered by the other verions here:
The disadvantages are:
The dependencies are somewhat mixed at the moment. I hope to improve this. At present, it needs:
pexports
utility from the mingw distribution (it would be possible to use DUMPBIN /EXPORTS
from MSVC, but parsing the output is a lot harder).
__declspec(naked)
is only supported by MSVC). I am working on finding an equivalent in Mingw, so that an all-Mingw approach is possible.
Note that this solution does not work for MSVC with x64, because the 'naked' attribute and the __asm commands are not supported with the x64 compiler.
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"}, " "))
To use the proxy, simply make the built lua51.dll
available on your PATH
, instead of the standard one. Extensions which statically link to lua51.dll
will pick this up and automatically use the static Lua runtime which is part of the main program. Of course, all normal C runtime issues still apply - the main program and any dynamically loaded extensions should use the same CRT or there could be issues (sadly, C doesn't offer a nice proxying solution like Lua does :-))
-- PaulMoore?