Lua 代理 DLL 四

lua-users home
wiki

这里又是一个用于 Lua 的代理 DLL 的配方。它专门用于允许静态链接的 Lua 安全地 `require()` 外部模块。此版本满足了其他版本中未涵盖的几个目的。

缺点是

目前,依赖关系有些混合。我希望改进这一点。目前,它需要

请注意,此解决方案不适用于使用 x64 的 MSVC,因为 'naked' 属性和 __asm 命令不受 x64 编译器的支持。

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`。静态链接到 `lua51.dll` 的扩展将拾取它并自动使用主程序中包含的静态 Lua 运行时。当然,所有正常的 C 运行时问题仍然适用 - 主程序和任何动态加载的扩展应该使用相同的 CRT,否则可能会出现问题(遗憾的是,C 没有像 Lua 那样提供很好的代理解决方案 :-))

-- PaulMoore?

另请参阅


最近更改 · 首选项
编辑 · 历史记录
上次编辑于 2019 年 11 月 15 日下午 10:04 GMT (差异)