Lua Proxy Dll Four

lua-users home
wiki

Here is yet another recipe for a proxy DLL for Lua. It is specifically to allow a statically linked Lua to safely 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:

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?

See Also


RecentChanges · preferences
edit · history
Last edited November 15, 2019 10:04 pm GMT (diff)