From 8d706b4ef942e01814f0a9db519aa32505b9abed Mon Sep 17 00:00:00 2001 From: aunsane Date: Fri, 29 Sep 2017 00:22:53 +0300 Subject: MirLua: added service functions to execute lua code version bump --- plugins/ExternalAPI/m_lua.h | 30 +++++++++++++ plugins/MirLua/src/main.cpp | 19 ++++++++ plugins/MirLua/src/mlua.cpp | 81 +++++++++++++++++++++++++++++++++- plugins/MirLua/src/mlua.h | 4 ++ plugins/MirLua/src/mlua_enviroment.cpp | 28 ++++++------ plugins/MirLua/src/mlua_enviroment.h | 5 +-- plugins/MirLua/src/mlua_options.cpp | 8 ++-- plugins/MirLua/src/mlua_script.cpp | 63 +++++++++++++------------- plugins/MirLua/src/mlua_script.h | 7 +-- plugins/MirLua/src/stdafx.h | 7 +++ plugins/MirLua/src/version.h | 2 +- 11 files changed, 199 insertions(+), 55 deletions(-) diff --git a/plugins/ExternalAPI/m_lua.h b/plugins/ExternalAPI/m_lua.h index 5d3fcda7bc..0a87455607 100644 --- a/plugins/ExternalAPI/m_lua.h +++ b/plugins/ExternalAPI/m_lua.h @@ -1,4 +1,34 @@ #ifndef _M_LUA_H_ #define _M_LUA_H_ +// Call lua function from module +// wParam = module name (or NULL for global function) +// lParam = function name +// Returns a pointer to the resolved string +#define MS_LUA_CALL "Lua/Call" + +__inline static wchar_t *lua_call(const wchar_t *module, const wchar_t *function) { + return (wchar_t*)CallService(MS_LUA_CALL, (WPARAM)module, (LPARAM)function); +} + +// Execute lua script from file +// wParam = NULL +// lParam = file path +// Returns a pointer to the resolved string +#define MS_LUA_EXEC "Lua/Exec" + +__inline static wchar_t *lua_exec(const wchar_t *path) { + return (wchar_t*)CallService(MS_LUA_EXEC, NULL, (LPARAM)path); +} + +// Evaluate lua script from string +// wParam = NULL +// lParam = lua script +// Returns a pointer to the resolved string +#define MS_LUA_EVAL "Lua/Eval" + +__inline static wchar_t *lua_eval(const wchar_t *script) { + return (wchar_t*)CallService(MS_LUA_EVAL, NULL, (LPARAM)script); +} + #endif //_M_LUA_H_ diff --git a/plugins/MirLua/src/main.cpp b/plugins/MirLua/src/main.cpp index 0da7a5d157..0dd0488d5c 100644 --- a/plugins/MirLua/src/main.cpp +++ b/plugins/MirLua/src/main.cpp @@ -54,6 +54,21 @@ int OnModulesLoaded(WPARAM, LPARAM) return 0; } +INT_PTR Call(WPARAM wParam, LPARAM lParam) +{ + return g_mLua->Call(wParam, lParam); +} + +INT_PTR Exec(WPARAM wParam, LPARAM lParam) +{ + return g_mLua->Exec(wParam, lParam); +} + +INT_PTR Eval(WPARAM wParam, LPARAM lParam) +{ + return g_mLua->Eval(wParam, lParam); +} + extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); @@ -75,6 +90,10 @@ extern "C" int __declspec(dllexport) Load(void) hRecvMessage = CreateHookableEvent(MODULE PSR_MESSAGE); CreateProtoServiceFunction(MODULE, PSR_MESSAGE, FilterRecvMessage); + CreateServiceFunction(MS_LUA_CALL, Call); + CreateServiceFunction(MS_LUA_EXEC, Exec); + CreateServiceFunction(MS_LUA_EVAL, Eval); + return 0; } diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp index 5229196f64..4dc3a2775a 100644 --- a/plugins/MirLua/src/mlua.cpp +++ b/plugins/MirLua/src/mlua.cpp @@ -265,7 +265,6 @@ void CMLua::Unload() { CMLuaScript *script = g_mLua->Scripts[last - 1]; Scripts.remove(script); - script->Unload(); delete script; } @@ -304,3 +303,83 @@ void CMLua::KillLuaRefs() } } } + +/***********************************************/ + +static int mlua_call(lua_State *L) +{ + const char *module = luaL_checkstring(L, -3); + const char *function = luaL_checkstring(L, -2); + + if (module && module[0]) + { + lua_getglobal(L, "require"); + lua_pushstring(L, module); + lua_pcall(L, 1, 1, 0); + + lua_getfield(L, -1, function); + lua_replace(L, -2); + } + else + lua_getglobal(L, function); + + lua_pcall(L, 0, 1, 0); + + return 1; +} + +INT_PTR CMLua::Call(WPARAM wParam, LPARAM lParam) +{ + const wchar_t *module = (const wchar_t*)wParam; + const wchar_t *function = (const wchar_t*)lParam; + + lua_pushstring(L, ptrA(mir_utf8encodeW(module))); + lua_pushstring(L, ptrA(mir_utf8encodeW(function))); + + lua_newtable(L); + lua_pushcclosure(L, mlua_call, 1); + + CMLuaEnviroment env(L); + env.Load(); + + wchar_t *result = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + return (INT_PTR)result; +} + +INT_PTR CMLua::Exec(WPARAM, LPARAM lParam) +{ + const wchar_t *path = (const wchar_t*)lParam; + + if (luaL_loadfile(L, ptrA(mir_utf8encodeW(path)))) { + ReportError(L); + return NULL; + } + + CMLuaEnviroment env(L); + env.Load(); + + wchar_t *result = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + return (INT_PTR)result; +} + +INT_PTR CMLua::Eval(WPARAM, LPARAM lParam) +{ + const wchar_t *script = (const wchar_t*)lParam; + + if (luaL_loadstring(L, ptrA(mir_utf8encodeW(script)))) { + ReportError(L); + return NULL; + } + + CMLuaEnviroment env(L); + env.Load(); + + wchar_t *result = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + return (INT_PTR)result; +} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua.h b/plugins/MirLua/src/mlua.h index c732d2c8a4..06f4fe2287 100644 --- a/plugins/MirLua/src/mlua.h +++ b/plugins/MirLua/src/mlua.h @@ -30,6 +30,10 @@ public: void Load(); void Unload(); + + INT_PTR Call(WPARAM, LPARAM); + INT_PTR Exec(WPARAM, LPARAM); + INT_PTR Eval(WPARAM, LPARAM); }; #endif //_LUA_CORE_H_ diff --git a/plugins/MirLua/src/mlua_enviroment.cpp b/plugins/MirLua/src/mlua_enviroment.cpp index 5d3b7cf37c..268afc46b0 100644 --- a/plugins/MirLua/src/mlua_enviroment.cpp +++ b/plugins/MirLua/src/mlua_enviroment.cpp @@ -9,6 +9,17 @@ CMLuaEnviroment::CMLuaEnviroment(lua_State *L) id = GetPluginLangId(muidLast, 0); } +CMLuaEnviroment::~CMLuaEnviroment() +{ + KillModuleIcons(id); + KillModuleSounds(id); + KillModuleMenus(id); + KillModuleHotkeys(id); + + KillObjectEventHooks(this); + KillObjectServices(this); +} + CMLuaEnviroment* CMLuaEnviroment::GetEnviroment(lua_State *L) { if (!luaM_getenv(L)) @@ -49,23 +60,12 @@ void CMLuaEnviroment::CreateEnviromentTable() lua_setmetatable(L, -2); } -bool CMLuaEnviroment::Load(int ind) +bool CMLuaEnviroment::Load() { - luaL_checktype(L, ind, LUA_TFUNCTION); + luaL_checktype(L, -1, LUA_TFUNCTION); CreateEnviromentTable(); lua_setupvalue(L, -2, 1); - return luaM_pcall(L, 0, 1) == LUA_OK; + return lua_pcall(L, 0, 1, 0) == LUA_OK; } - -void CMLuaEnviroment::Unload() -{ - KillModuleIcons(id); - KillModuleSounds(id); - KillModuleMenus(id); - KillModuleHotkeys(id); - - KillObjectEventHooks(this); - KillObjectServices(this); -} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_enviroment.h b/plugins/MirLua/src/mlua_enviroment.h index 4366d58d03..73f3f9c377 100644 --- a/plugins/MirLua/src/mlua_enviroment.h +++ b/plugins/MirLua/src/mlua_enviroment.h @@ -12,15 +12,14 @@ public: lua_State *L; CMLuaEnviroment(lua_State *L); - virtual ~CMLuaEnviroment() { } + virtual ~CMLuaEnviroment(); static CMLuaEnviroment* GetEnviroment(lua_State *L); static int GetEnviromentId(lua_State *L); int GetId() const; - bool Load(int ind); - void Unload(); + bool Load(); }; #endif //_LUA_ENVIROMENT_H_ diff --git a/plugins/MirLua/src/mlua_options.cpp b/plugins/MirLua/src/mlua_options.cpp index 65325e00dc..b4e11cb01d 100644 --- a/plugins/MirLua/src/mlua_options.cpp +++ b/plugins/MirLua/src/mlua_options.cpp @@ -121,7 +121,7 @@ void CMLuaOptions::OnScriptListClick(CCtrlListView::TEventInfo *evt) evt->treeviewctrl->GetItem(&lvi); lvi.iSubItem = evt->nmlvia->iSubItem; - CMLuaScript* script = (CMLuaScript*)lvi.lParam; + CMLuaScript *script = (CMLuaScript*)lvi.lParam; switch (lvi.iSubItem) { @@ -130,9 +130,11 @@ void CMLuaOptions::OnScriptListClick(CCtrlListView::TEventInfo *evt) break; case 2: - //m_scripts.DeleteItem(evt->nmlvia->iItem); - script->Unload(); + lvi.lParam = (LPARAM)new CMLuaScript(*script); + delete script; + script = (CMLuaScript*)lvi.lParam; script->Load(); + lvi.mask = LVIF_IMAGE; lvi.iSubItem = 0; lvi.iImage = script->GetStatus() - 1; diff --git a/plugins/MirLua/src/mlua_script.cpp b/plugins/MirLua/src/mlua_script.cpp index 6fbcfc9ac7..8b56674230 100644 --- a/plugins/MirLua/src/mlua_script.cpp +++ b/plugins/MirLua/src/mlua_script.cpp @@ -3,7 +3,7 @@ #define MT_SCRIPT "SCRIPT" CMLuaScript::CMLuaScript(lua_State *L, const wchar_t *path) - : CMLuaEnviroment(L) + : CMLuaEnviroment(L), status(None), unloadRef(LUA_NOREF) { mir_wstrcpy(filePath, path); @@ -18,9 +18,33 @@ CMLuaScript::CMLuaScript(lua_State *L, const wchar_t *path) moduleName = mir_utf8encodeW(name); } +CMLuaScript::CMLuaScript(const CMLuaScript &script) + : CMLuaEnviroment(L), status(None), unloadRef(LUA_NOREF) +{ + mir_wstrcpy(filePath, script.filePath); + fileName = mir_wstrdup(script.fileName); + moduleName = mir_strdup(script.moduleName); +} + CMLuaScript::~CMLuaScript() { + if (status == Loaded) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, unloadRef); + if (lua_isfunction(L, -1)) + luaM_pcall(L); + lua_pushnil(L); + lua_rawsetp(L, LUA_REGISTRYINDEX, this); + status = None; + } + + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_pushnil(L); + lua_setfield(L, -2, moduleName); + lua_pop(L, 1); + mir_free(moduleName); + mir_free(fileName); } const char* CMLuaScript::GetModuleName() const @@ -38,7 +62,7 @@ const wchar_t* CMLuaScript::GetFileName() const return fileName; } -const CMLuaScript::Status CMLuaScript::GetStatus() const +CMLuaScript::Status CMLuaScript::GetStatus() const { return status; } @@ -47,14 +71,15 @@ bool CMLuaScript::Load() { status = Failed; - if (luaL_loadfile(L, _T2A(filePath))) - { - Log(lua_tostring(L, -1)); + if (luaL_loadfile(L, _T2A(filePath))) { + ReportError(L); return false; } - if (!CMLuaEnviroment::Load(-1)) + if (!CMLuaEnviroment::Load()) { + ReportError(L); return false; + } status = Loaded; @@ -63,8 +88,7 @@ bool CMLuaScript::Load() luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, -1, moduleName); - if (!lua_toboolean(L, -1)) - { + if (!lua_toboolean(L, -1)) { lua_pop(L, 1); lua_pushvalue(L, -2); lua_setfield(L, -2, moduleName); @@ -83,8 +107,7 @@ bool CMLuaScript::Load() lua_pop(L, 1); lua_getfield(L, -1, "Unload"); - if (lua_isfunction(L, -1)) - { + if (lua_isfunction(L, -1)) { lua_pushvalue(L, -1); unloadRef = luaL_ref(L, LUA_REGISTRYINDEX); } @@ -93,24 +116,4 @@ bool CMLuaScript::Load() lua_pop(L, 1); return true; -} - -void CMLuaScript::Unload() -{ - if (status == Loaded) - { - lua_rawgeti(L, LUA_REGISTRYINDEX, unloadRef); - if (lua_isfunction(L, -1)) - luaM_pcall(L); - lua_pushnil(L); - lua_rawsetp(L, LUA_REGISTRYINDEX, this); - status = None; - } - - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_pushnil(L); - lua_setfield(L, -2, moduleName); - lua_pop(L, 1); - - CMLuaEnviroment::Unload(); } \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_script.h b/plugins/MirLua/src/mlua_script.h index 2b5d57d7c7..36008d063b 100644 --- a/plugins/MirLua/src/mlua_script.h +++ b/plugins/MirLua/src/mlua_script.h @@ -12,14 +12,16 @@ public: }; private: + Status status; int unloadRef; + char *moduleName; wchar_t *fileName; wchar_t filePath[MAX_PATH]; - Status status; public: CMLuaScript(lua_State *L, const wchar_t *path); + CMLuaScript(const CMLuaScript &script); ~CMLuaScript(); const char* GetModuleName() const; @@ -27,10 +29,9 @@ public: const wchar_t* GetFilePath() const; const wchar_t* GetFileName() const; - const Status GetStatus() const; + Status GetStatus() const; bool Load(); - void Unload(); }; #endif //_LUA_SCRIPT_H_ diff --git a/plugins/MirLua/src/stdafx.h b/plugins/MirLua/src/stdafx.h index d9fb9febc4..08b15a246e 100644 --- a/plugins/MirLua/src/stdafx.h +++ b/plugins/MirLua/src/stdafx.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -91,6 +92,10 @@ LUAMOD_API int (luaopen_m_sounds)(lua_State *L); #define MLUA_SRMM "m_srmm" LUAMOD_API int (luaopen_m_srmm)(lua_State *L); +/* services */ + +INT_PTR Call(WPARAM wParam, LPARAM lParam); + /* utils */ extern HNETLIBUSER hNetlib; @@ -101,6 +106,8 @@ void ShowNotification(const char *caption, const char *message, int flags = 0, M void ObsoleteMethod(lua_State *L, const char *message); +void ReportError(lua_State *L); + int luaM_atpanic(lua_State *L); int luaM_pcall(lua_State *L, int n = 0, int r = 0); diff --git a/plugins/MirLua/src/version.h b/plugins/MirLua/src/version.h index 6b783b7c7b..4f3f3a4c6e 100644 --- a/plugins/MirLua/src/version.h +++ b/plugins/MirLua/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 11 #define __RELEASE_NUM 8 -#define __BUILD_NUM 3 +#define __BUILD_NUM 4 #include -- cgit v1.2.3