Lua Proxy Dll |
|
-- expand.lua - Generates Lua proxy DLL source code. local function map(f, t) local t = {unpack(t)} for k,v in ipairs(t) do t[k] = f(v) end return t end local function foreach(fmt, t) return table.concat(map(function(s) return string.format(fmt, s) end, t)) end -- API functions defined in LuaBinaries - http://luabinaries.luaforge.net/ local apifuncs = { "lua_tolstring","lua_typename","lua_pushfstring","lua_pushvfstring", "lua_getlocal","lua_getupvalue","lua_setlocal","lua_setupvalue", "lua_topointer","lua_iscfunction","lua_isnumber","lua_isstring", "lua_isuserdata","lua_toboolean","lua_type","lua_equal", "lua_lessthan","lua_rawequal","lua_checkstack","lua_cpcall", "lua_error","lua_getmetatable","lua_gettop","lua_load", "lua_next","lua_pcall","lua_pushthread","lua_setfenv", "lua_setmetatable","lua_resume","lua_status","lua_yield", "lua_dump","lua_gc","lua_gethook","lua_gethookcount", "lua_gethookmask","lua_getinfo","lua_getstack","lua_sethook", "lua_getallocf","lua_tocfunction","lua_atpanic","lua_tointeger", "lua_tonumber","lua_tothread","lua_newstate","lua_newthread", "lua_objlen","lua_touserdata","lua_close","lua_call", "lua_concat","lua_createtable","lua_getfenv","lua_getfield", "lua_gettable","lua_insert","lua_pushboolean","lua_pushcclosure", "lua_pushinteger","lua_pushlightuserdata","lua_pushlstring", "lua_pushnil","lua_pushnumber","lua_pushstring","lua_pushvalue", "lua_rawget","lua_rawgeti","lua_rawset","lua_rawseti", "lua_remove","lua_replace","lua_setfield","lua_settable", "lua_settop","lua_xmove","lua_newuserdata","lua_setallocf", "luaL_prepbuffer","luaL_checklstring","luaL_findtable","luaL_gsub", "luaL_optlstring","luaL_newmetatable","luaL_argerror","luaL_callmeta", "luaL_checkoption","luaL_error","luaL_getmetafield","luaL_loadbuffer", "luaL_loadfile","luaL_loadstring","luaL_ref","luaL_typerror", "luaL_checkinteger","luaL_optinteger","luaL_checknumber", "luaL_optnumber","luaL_newstate","luaL_openlib","luaL_addlstring", "luaL_addstring","luaL_addvalue","luaL_buffinit","luaL_checkany", "luaL_checkstack","luaL_checktype","luaL_pushresult","luaL_register", "luaL_unref","luaL_where","luaL_checkudata","luaopen_base", "luaopen_debug","luaopen_io","luaopen_math","luaopen_os", "luaopen_package","luaopen_string","luaopen_table","luaL_openlibs", "luaU_dump","luaM_toobig","luaM_realloc_","luaS_newlstr", "luaD_growstack","luaF_newproto" } local luaproxydll_h = [[ /** luaproxydll.h - C header file for Lua proxy DLL (lua5.1.dll). (autogenerated from expand.lua) == Discussion == Lua extension modules in Windows typically dynamically link against the lua5.1.dll defined in Lua Binaries (http://luabinaries.luaforge.net/). This assumes your EXE also dynamically links against lua5.1.dll. If your EXE instead statically links against lua5.1.dll, then you have two copies of the Lua core, which is redundant and also can cause subtle problems. The proxy DLL defined here is a drop-in-replacement for the standard lua5.1.dll. It acts as a thin proxy that exports the same interface as the standard lua5.1.dll and transparently forwards calls to the Lua core functions defined in the EXE. Before extension modules attempt to load and call the proxy DLL, the EXE must load the proxy DLL and call the additional proxy_init() function in the proxy DLL, passing it the addresses of the Lua core functions in the EXE. The resultant DLL should be small (less than 10K). The compilation can omit the C run-time. To use this in your EXE, include luaproxydll.h and then run LUAPROXYDLL_INIT(). You may need to remove the "LUAI_FUNC" before these functions in the Lua source: luaU_dump luaM_toobig luaM_realloc_ luaS_newlstr luaD_growstack luaF_newproto Note: LUAPROXYDLL_IMPLEMENTATION is undefined in the EXE. Author: (c) David Manura, 2007-01-30 Licensed under the same terms as Lua 5.1 itself. */ #ifndef LUAPROXYDLL_H #define LUAPROXYDLL_H #ifdef __cplusplus extern "C" { #endif typedef const void * const luaproxydll_t; /** Pointers to Lua core functions in the EXE. The EXE should prepare this and pass it to the luaproxydll_init function. */ struct luaproxydll_Funcs { ]] .. foreach([[ luaproxydll_t %s; ]], apifuncs) .. [[ }; /* not passed: luaP_opmodes, luaP_opnames */ /* These are only used by the EXE */ #ifndef LUAPROXYDLL_IMPLEMENTATION /* reference Lua core functions */ #include <lua.h> #include <lauxlib.h> #include <lualib.h> /* void luaU_dump(); void luaM_toobig(); void luaM_realloc_(); void luaS_newlstr(); void luaD_growstack(); void luaF_newproto(); */ #include <lfunc.h> #include <lundump.h> #include <lstring.h> #include <ldo.h> /** Table of Lua core function pointers. */ const struct luaproxydll_Funcs luaproxydll_funcs = { ]] .. foreach([[ %s, ]], apifuncs) .. [[ }; /* not passed: luaP_opmodes, luaP_opnames */ /** load proxy DLL. Call this in your EXE to load and initialize the proxy DLL. */ #define LUAPROXYDLL_INIT() \ { \ HMODULE hmodule = LoadLibrary("lua5.1.dll"); \ if (hmodule) { \ typedef void (*func_t)(const luaproxydll_Funcs *); \ func_t initfunc = (func_t)GetProcAddress(hmodule, "luaproxydll_init"); \ if (initfunc) { \ initfunc(&luaproxydll_funcs); \ } \ } \ } /* Register Lua core functions from the EXE into the proxy DLL. funcs must remain valid until the proxy DLL is unloaded or no longer used. */ void luaproxydll_init(struct luaproxydll_Funcs * funcs); #endif /* not LUAPROXYDLL_IMPLEMENTATION */ #ifdef __cplusplus } #endif #endif /* first include */ ]] local luaproxydll_c = [[ /*** luaproxydll.c - C implementation file for the Lua proxy dll. (autogenerated from expand.lua) Author: (c) David Manura, 2007-01-30 Licensed under the same terms as Lua 5.1 itself. ***/ #define LUAPROXYDLL_IMPLEMENTATION /* used by luaproxydll.h */ #include <windows.h> #include "luaproxydll.h" static struct luaproxydll_Funcs 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 PROXY(name) \ void __declspec(naked) name() { __asm { jmp s_funcs.name } } /* Define all the proxy functions specified in lua5.1.def. */ ]] .. foreach([[ PROXY(%s) ]], apifuncs) .. [[ /* note: luaP_opmodes and luaP_opnames are defined in lopcodes.c */ BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID reserved) { /* DEBUG: MessageBox(NULL, "proxyload", "", MB_OK); */ return TRUE; } void luaproxydll_init(struct luaproxydll_Funcs * funcs) { int n; for (n=0; n < sizeof(struct luaproxydll_Funcs); n++) { ((unsigned char*)(void*)&s_funcs)[n] = ((unsigned char*)(void*)funcs)[n]; } /* nope: s_funcs = funcs; */ } ]] local GNUmakefile = [[ # GNUmakefile - Makefile for luaproxydll.dll for MSVC compiler. # (autogenerated from expand.lua) all: cl /O2 /LD /GS- luaproxydll.c ../lua/src/lopcodes.c \ /link /def:lua5.1.def /out:lua5.1.dll /nodefaultlib /entry:DllMain clean: rm -f *~ *.obj *.exp *.lib purge: clean rm -f luaproxydll.[hc] lua5.1.def GNUmakefile lua5.1.dll ]] local lua5_1_def = [[ ; lua5.1.def ; (autogenerated from expand.lua) VERSION 5.1 EXPORTS ]] .. foreach([[ %s ]], apifuncs) .. [[ luaP_opmodes luaP_opnames ; special luaproxydll_init ]] for k,v in pairs{ [luaproxydll_h] = "luaproxydll.h", [luaproxydll_c] = "luaproxydll.c", [lua5_1_def] = "lua5.1.def", [GNUmakefile] = "GNUmakefile" } do io.output(v); io.write(k) end
David, what are the benefits of the above configuration over the common one (lua.exe + lua5.1.dll)? --ShmuelZeigerman
You can also use this trick (I used version 3 below) to make a normal looking lua5.1.dll that proxies to a tweaked distribution like LuaPlus_1100.dll. Once again for the purpose of letting LuaBinaries dll's work. --ferrix
Any ideas for making these page names more descriptive?