Lua 中调用 Windows API
#include "lua.h" #include <malloc.h> #include <windows.h> typedef void* (__stdcall *func_call)(); static int api_call(lua_State *L) { int i,type; int n=lua_gettop(L); func_call fc=(func_call)lua_touserdata(L,lua_upvalueindex(2)); void *ret; do { void **arg=(void **)_alloca(n*sizeof(void *)); for (i=0;i<n;i++) { type=lua_type(L,i+1); switch(type) { case LUA_TNIL: arg[i]=0; break; case LUA_TNUMBER: arg[i]=(void*)lua_tointeger(L,i+1); break; case LUA_TBOOLEAN: arg[i]=(void*)lua_toboolean(L,i+1); break; case LUA_TSTRING: arg[i]=(void *)lua_tostring(L,i+1); break; case LUA_TLIGHTUSERDATA: arg[i]=lua_touserdata(L,i+1); break; default: lua_pushstring(L,"unknown argument type"); lua_error(L); break; } } ret=fc(); } while(0); switch(lua_type(L,lua_upvalueindex(1))) { case LUA_TNIL: lua_pushlightuserdata(L,ret); break; case LUA_TNUMBER: lua_pushinteger(L,(int)ret); break; case LUA_TBOOLEAN: lua_pushboolean(L,(int)ret); break; case LUA_TSTRING: lua_pushstring(L,(const char*)ret); break; default: lua_pushstring(L,"unknown return value type"); lua_error(L); break; } return 1; } static int open_dll(lua_State *L) { const char *name=lua_tostring(L,1); HMODULE hm=LoadLibrary(name); lua_pushlightuserdata(L,hm); return 1; } static int get_procaddress(lua_State *L) { HMODULE hm=(HMODULE)lua_touserdata(L,1); const char *name=lua_tostring(L,2); void *func=GetProcAddress(hm,name); lua_pushvalue(L,3); lua_pushlightuserdata(L,func); lua_pushcclosure(L,api_call,2); return 1; } __declspec(dllexport) int luaopen_api_procaddress(lua_State *L) { lua_pushcfunction(L,get_procaddress); return 1; } __declspec(dllexport) int luaopen_api_opendll(lua_State *L) { lua_pushcfunction(L,open_dll); return 1; }
下面,我们可以在 lua 中调用 windows 的 api 了,用法大约是这样的:
opendll = require("api.opendll") getprocaddress =require("api.procaddress") user32=opendll("user32.dll") MessageBox=getprocaddress(user32,"MessageBoxA") MessageBox(nil,"hello","hehe",0)