//---------------------------------------------------------------------------- // EgalTech 2015-2017 //---------------------------------------------------------------------------- // File : LuaManager.cpp Data : 03.01.17 Versione : 1.6x1 // Contenuto : Implementazione della classe LuaMgr. // // // // Modifiche : 21.03.15 DS Creazione modulo. // 20.08.15 DS Controllo che il double di EvalExpr sia numero valido. // 03.01.17 DS Aggiunti controlli validità ambiente lua. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DllMain.h" #include "/EgtDev/Include/EGnLuaMgr.h" #include "/EgtDev/Include/EgtILogger.h" #include "/EgtDev/Extern/Lua/Include/lua.hpp" using namespace std ; //---------------------------------------------------------------------------- bool LuaMgr::Init( void) { // se già aperto, lo fermo per riavviarlo if ( m_pL != nullptr) { lua_close( m_pL) ; m_pL = nullptr ; } // inizializzo Lua m_pL = luaL_newstate() ; if ( m_pL == nullptr) { LOG_ERROR( GetEGnLogger(), "Error in Lua interpreter starting (LuaMgr::Init)") return false ; } // carico le librerie standard luaL_openlibs( m_pL) ; return true ; } //---------------------------------------------------------------------------- bool LuaMgr::Exit( void) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // termino Lua lua_close( m_pL) ; m_pL = nullptr ; return true ; } //---------------------------------------------------------------------------- bool LuaMgr::GetVersion( string& sLuaVer) const { // verifico ambiente lua if ( m_pL == nullptr) return false ; // verifico il parametro di ritorno if ( &sLuaVer == nullptr) return false ; // recupero la versione di Lua lua_getglobal( m_pL, "_VERSION") ; if ( LuaGetParam( m_pL, - 1, sLuaVer)) return true ; else return false ; } //---------------------------------------------------------------------------- bool LuaMgr::SetLuaLibsDir( const string& sDir) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // salvo il direttorio m_sLuaLibsDir = sDir ; // recupero la stringa globale package.path lua_getglobal( m_pL, "package") ; lua_getfield( m_pL, -1, "path") ; string sCurPath = lua_tostring( m_pL, -1) ; // verifico se la dir ricevuta è già presente if ( sCurPath.find( sDir) != string::npos) { lua_pop( m_pL, 2) ; return true ; } // imposto la nuova dir sCurPath = sDir ; sCurPath += "\\?.lua" ; lua_pop( m_pL, 1) ; lua_pushstring( m_pL, sCurPath.c_str()) ; lua_setfield( m_pL, -2, "path") ; lua_pop( m_pL, 1) ; return true ; } //---------------------------------------------------------------------------- bool LuaMgr::Require( const string& sFile) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // salvo nome libreria richiesta m_sLastRequire = sFile ; // eseguo lua_getglobal( m_pL, "require") ; lua_pushstring( m_pL, sFile.c_str()) ; int nErr = lua_pcall( m_pL, 1, 1, 0) ; /* call 'require(sFile)' */ if ( nErr == LUA_OK) { lua_setglobal( m_pL, sFile.c_str()) ; /* global[sFile] = require return */ m_sLastError.clear() ; return true ; } else { // recupero il messaggio di errore const char* szErr = lua_tostring( m_pL, -1) ; m_sLastError = ( szErr != nullptr) ? szErr : "Error unknown" ; lua_pop( m_pL, 1) ; // lo scrivo nel log LOG_ERROR( GetEGnLogger(), m_sLastError.c_str()) return false ; } } //---------------------------------------------------------------------------- bool LuaMgr::RegisterFunction( const string& sFunName, PFLUA pFun) { // verifico ambiente lua if ( m_pL == nullptr) return false ; if ( &sFunName == nullptr) return false ; try { lua_register( m_pL, sFunName.c_str(), pFun) ; } catch ( ...) { return false ; } return true ; } //---------------------------------------------------------------------------- bool LuaMgr::EvalExpr( const string& sExpr, double& dVal) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // completo la stringa da valutare string sEval = "return " + sExpr ; // valuto l'espressione int nErr = luaL_loadstring( m_pL, sEval.c_str()) ; if ( nErr == LUA_OK) nErr = lua_pcall( m_pL, 0, 1, 0) ; // senza errori if ( nErr == LUA_OK && lua_type( m_pL, -1) == LUA_TNUMBER) { dVal = lua_tonumber( m_pL, -1) ; lua_pop( m_pL, 1) ; if ( ! isinf( dVal) && ! isnan( dVal)) { m_sLastError.clear() ; return true ; } else { m_sLastError = "EvalExpr(number): Error infinite or not a number" ; // lo scrivo nel log LOG_ERROR( GetEGnLogger(), m_sLastError.c_str()) return false ; } } // altrimenti, errore else { // recupero il messaggio di errore const char* szErr = lua_tostring( m_pL, -1) ; m_sLastError = string( "EvalExpr(number): ") + (( szErr != nullptr) ? szErr : "Error not a number") ; lua_pop( m_pL, 1) ; // lo scrivo nel log LOG_ERROR( GetEGnLogger(), m_sLastError.c_str()) return false ; } } //---------------------------------------------------------------------------- bool LuaMgr::EvalExpr( const string& sExpr, string& sVal) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // completo la stringa da valutare string sEval = "return " + sExpr ; // valuto l'espressione int nErr = luaL_loadstring( m_pL, sEval.c_str()) ; if ( nErr == LUA_OK) nErr = lua_pcall( m_pL, 0, 1, 0) ; // senza errori if ( nErr == LUA_OK && lua_type( m_pL, -1) == LUA_TSTRING) { sVal = lua_tostring( m_pL, -1) ; lua_pop( m_pL, 1) ; m_sLastError.clear() ; return true ; } // altrimenti, errore else { // recupero il messaggio di errore const char* szErr = lua_tostring( m_pL, -1) ; m_sLastError = string( "EvalExpr(string): ") + (( szErr != nullptr) ? szErr : "Error not a string") ; lua_pop( m_pL, 1) ; // lo scrivo nel log LOG_ERROR( GetEGnLogger(), m_sLastError.c_str()) return false ; } } //---------------------------------------------------------------------------- bool LuaMgr::ExecLine( const string& sLine) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // eseguo la linea int nErr = luaL_loadstring( m_pL, sLine.c_str()) ; if ( nErr == LUA_OK) nErr = lua_pcall( m_pL, 0, LUA_MULTRET, 0) ; // senza errori if ( nErr == LUA_OK) { m_sLastError.clear() ; return true ; } // altrimenti, errore else { // recupero il messaggio di errore const char* szErr = lua_tostring( m_pL, -1) ; m_sLastError = string( "ExecLine: ") + (( szErr != nullptr) ? szErr : "Error unknown") ; lua_pop( m_pL, 1) ; // lo scrivo nel log LOG_ERROR( GetEGnLogger(), m_sLastError.c_str()) return false ; } } //---------------------------------------------------------------------------- bool LuaMgr::ExecFile( const string& sFile) { // verifico ambiente lua if ( m_pL == nullptr) return false ; // eseguo la linea int nErr = luaL_loadfile( m_pL, sFile.c_str()) ; if ( nErr == LUA_OK) nErr = lua_pcall( m_pL, 0, LUA_MULTRET, 0) ; // senza errori if ( nErr == LUA_OK) { m_sLastError.clear() ; return true ; } // in caso di errore else { // recupero il messaggio di errore const char* szErr = lua_tostring( m_pL, -1) ; m_sLastError = (( szErr != nullptr) ? szErr : "Error unknown") ; lua_pop( m_pL, 1) ; // lo scrivo nel log LOG_ERROR( GetEGnLogger(), m_sLastError.c_str()) return false ; } } //---------------------------------------------------------------------------- bool LuaMgr::ExistsFunction( const string& sFunName) const { // verifico ambiente lua if ( m_pL == nullptr) return false ; // recupero la funzione if ( sFunName.find( '.') == string::npos) { // è direttamente il nome lua_getglobal( m_pL, sFunName.c_str()) ; } else { // è in una tavola string sTab, sField ; SplitFirst( sFunName, ".", sTab, sField) ; lua_getglobal( m_pL, sTab.c_str()) ; lua_getfield( m_pL, -1, sField.c_str()) ; // porto la funzione uno slot sotto e diminuisco lo stack di uno (per essere come caso sopra) lua_copy( m_pL, -1, -2) ; lua_pop( m_pL, 1) ; } bool bOk = ( lua_isfunction( m_pL, -1) != 0) ; lua_pop( m_pL, 1) ; return bOk ; } //---------------------------------------------------------------------------- void LuaMgr::LogError( const string& sErr) const { LOG_ERROR( GetEGnLogger(), sErr.c_str()) }