diff options
| author | 2016-04-21 03:01:17 -0400 | |
|---|---|---|
| committer | 2016-04-21 03:12:20 -0400 | |
| commit | c33327ff43db2e0fd8f4c2d9a7a4333a50e8c605 (patch) | |
| tree | ba8c64caaf02b9d65607022c6f5b3dd0fffb8dfb /src/modules | |
| parent | Merge pull request #1951 from AlexanderP/travis_ppa (diff) | |
| download | KVIrc-c33327ff43db2e0fd8f4c2d9a7a4333a50e8c605.tar.gz KVIrc-c33327ff43db2e0fd8f4c2d9a7a4333a50e8c605.tar.bz2 KVIrc-c33327ff43db2e0fd8f4c2d9a7a4333a50e8c605.zip | |
Python: Refactor python support
Closes #1866
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/python/libkvipython.cpp | 27 | ||||
| -rw-r--r-- | src/modules/pythoncore/kvircmodule.cpp | 124 | ||||
| -rw-r--r-- | src/modules/pythoncore/kvircmodule.h | 22 | ||||
| -rw-r--r-- | src/modules/pythoncore/libkvipythoncore.cpp | 296 |
4 files changed, 178 insertions, 291 deletions
diff --git a/src/modules/python/libkvipython.cpp b/src/modules/python/libkvipython.cpp index 7d99636d5..e9ebfb9dd 100644 --- a/src/modules/python/libkvipython.cpp +++ b/src/modules/python/libkvipython.cpp @@ -31,7 +31,7 @@ #include "../pythoncore/pythoncoreinterface.h" #include <Python.h> - static KviModule * g_pPythonCoreModule = 0; + static KviModule * g_pPythonCoreModule = nullptr; #define KVS_CHECK_PYTHONCORE(_m,_c) \ g_pPythonCoreModule = g_pModuleManager->getModule("pythoncore"); \ @@ -56,7 +56,7 @@ _c->warning(__tr2qs_ctx("This KVIrc executable has been compiled without Python scripting support","python")); \ return true; - static KviModule * g_pPythonCoreModule = 0; + static KviModule * g_pPythonCoreModule = nullptr; #endif // COMPILE_PYTHON_SUPPORT /* @@ -430,25 +430,17 @@ static bool python_kvs_cmd_begin(KviKvsModuleCommandCall * c) if(!ex.lWarnings.isEmpty()) { - for(QStringList::Iterator it = ex.lWarnings.begin();it != ex.lWarnings.end();++it) - c->warning(*it); + for(const auto& it : ex.lWarnings) + c->warning(it); } - if(!ex.bExitOk) + if(!ex.bExitOk && !c->switches()->find('q',"quiet")) { - if(!c->switches()->find('q',"quiet")) - { + c->warning(__tr2qs_ctx("Python execution error:","python")); + c->warning(ex.szError); - if(c->switches()->find('f',"fail-on-error")) - { - c->warning(__tr2qs_ctx("Python execution error:","python")); - c->warning(ex.szError); - return false; - } else { - c->warning(__tr2qs_ctx("Python execution error:","python")); - c->error(ex.szError); - } - } + if(c->switches()->find('f',"fail-on-error")) + return false; } if(!c->switches()->find('n',"no-return")) @@ -456,7 +448,6 @@ static bool python_kvs_cmd_begin(KviKvsModuleCommandCall * c) #endif //COMPILE_PYTHON_SUPPORT - return true; } diff --git a/src/modules/pythoncore/kvircmodule.cpp b/src/modules/pythoncore/kvircmodule.cpp index eac16903c..bc26c0759 100644 --- a/src/modules/pythoncore/kvircmodule.cpp +++ b/src/modules/pythoncore/kvircmodule.cpp @@ -48,10 +48,9 @@ extern QString g_lError; static PyObject * PyKVIrc_echo(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - const char * pcText=0; - int iColorSet=0; - const char * pcWinId=0; - KviWindow * pWnd=0; + const char * pcText = nullptr, *pcWinId = nullptr; + KviWindow * pWnd = nullptr; + int iColorSet = 0; if(QThread::currentThread() != g_pApp->thread()) { @@ -65,20 +64,18 @@ static PyObject * PyKVIrc_echo(PyObject * pSelf, PyObject * pArgs) if(pcText) { if(pcWinId) - { pWnd = g_pApp->findWindow(pcWinId); - } + if(!pWnd) { if(g_pCurrentKvsContext) - { pWnd = g_pCurrentKvsContext->window(); - } else if(g_pActiveWindow) { + else if(g_pActiveWindow) pWnd = g_pActiveWindow; - } else { - pWnd = (KviWindow*) g_pApp->activeConsole(); - } + else + pWnd = (KviWindow *) g_pApp->activeConsole(); } + if(pWnd) pWnd->outputNoFmt(iColorSet,QString::fromUtf8(pcText)); } @@ -89,10 +86,8 @@ static PyObject * PyKVIrc_echo(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_say(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - - const char * pcText=0; - const char * pcWinId=0; - KviWindow * pWnd=0; + const char * pcText = nullptr, *pcWinId = nullptr; + KviWindow * pWnd = nullptr; if(QThread::currentThread() != g_pApp->thread()) { @@ -106,23 +101,20 @@ static PyObject * PyKVIrc_say(PyObject * pSelf, PyObject * pArgs) if(pcText) { if(pcWinId) - { pWnd = g_pApp->findWindow(pcWinId); - } + if(!pWnd) { if(g_pCurrentKvsContext) - { pWnd = g_pCurrentKvsContext->window(); - } else if(g_pActiveWindow) { + else if(g_pActiveWindow) pWnd = g_pActiveWindow; - } else { - pWnd = (KviWindow*) g_pApp->activeConsole(); - } + else + pWnd = (KviWindow *) g_pApp->activeConsole(); } if(pWnd) { - QString szText=QString::fromUtf8(pcText); + QString szText = QString::fromUtf8(pcText); KviUserInput::parse(szText,pWnd); } } @@ -133,7 +125,7 @@ static PyObject * PyKVIrc_say(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_warning(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - const char * pcText=0; + const char * pcText = nullptr; if(QThread::currentThread() != g_pApp->thread()) { @@ -156,9 +148,8 @@ static PyObject * PyKVIrc_warning(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_getLocal(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - + const char * szVarName = nullptr; QString tmp; - const char * szVarName=0; if(QThread::currentThread() != g_pApp->thread()) { @@ -166,7 +157,6 @@ static PyObject * PyKVIrc_getLocal(PyObject * pSelf, PyObject * pArgs) return 0; // Sorry, we're NOT thread safe } - if(!PyArg_ParseTuple(pArgs,"s",&szVarName)) return 0; @@ -177,7 +167,9 @@ static PyObject * PyKVIrc_getLocal(PyObject * pSelf, PyObject * pArgs) { pVar->asString(tmp); return Py_BuildValue("s",tmp.toUtf8().data()); - } else return Py_BuildValue("s",""); + } else { + return Py_BuildValue("s",""); + } } return 0; } @@ -185,10 +177,8 @@ static PyObject * PyKVIrc_getLocal(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_setLocal(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - + const char * szVarName = nullptr, *szVarValue = nullptr; QString tmp; - const char * szVarName=0; - const char * szVarValue=0; if(QThread::currentThread() != g_pApp->thread()) { @@ -216,9 +206,8 @@ static PyObject * PyKVIrc_setLocal(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_getGlobal(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - + const char * szVarName = nullptr; QString tmp; - const char * szVarName=0; if(QThread::currentThread() != g_pApp->thread()) { @@ -236,7 +225,9 @@ static PyObject * PyKVIrc_getGlobal(PyObject * pSelf, PyObject * pArgs) { pVar->asString(tmp); return Py_BuildValue("s",tmp.toUtf8().data()); - } else return Py_BuildValue("s",""); + } else { + return Py_BuildValue("s",""); + } } return 0; } @@ -244,10 +235,8 @@ static PyObject * PyKVIrc_getGlobal(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_setGlobal(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - + const char * szVarName = nullptr, *szVarValue = nullptr; QString tmp; - const char * szVarName=0; - const char * szVarValue=0; if(QThread::currentThread() != g_pApp->thread()) { @@ -255,7 +244,6 @@ static PyObject * PyKVIrc_setGlobal(PyObject * pSelf, PyObject * pArgs) return 0; // Sorry, we're NOT thread safe } - if(!PyArg_ParseTuple(pArgs,"ss",&szVarName, &szVarValue)) return 0; @@ -276,9 +264,9 @@ static PyObject * PyKVIrc_setGlobal(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_eval(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - const char * pcCode=0; - char * pcRetVal=0; - KviWindow * pWnd=0; + const char * pcCode = nullptr; + KviWindow * pWnd = nullptr; + char * pcRetVal = nullptr; if(QThread::currentThread() != g_pApp->thread()) { @@ -292,13 +280,12 @@ static PyObject * PyKVIrc_eval(PyObject * pSelf, PyObject * pArgs) if(pcCode) { if(g_pCurrentKvsContext) - { pWnd = g_pCurrentKvsContext->window(); - } else if(g_pActiveWindow) { + else if(g_pActiveWindow) pWnd = g_pActiveWindow; - } else { - pWnd = (KviWindow*) g_pApp->activeConsole(); - } + else + pWnd = (KviWindow *) g_pApp->activeConsole(); + if(pWnd) { KviKvsVariant ret; @@ -317,7 +304,7 @@ static PyObject * PyKVIrc_eval(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_internalWarning(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - const char * pcText=0; + const char * pcText = nullptr; if(QThread::currentThread() != g_pApp->thread()) { @@ -329,9 +316,7 @@ static PyObject * PyKVIrc_internalWarning(PyObject * pSelf, PyObject * pArgs) return 0; if(pcText && !g_bExecuteQuiet) - { g_lWarningList.append(QString(pcText)); - } return Py_BuildValue("i",1); } @@ -339,7 +324,7 @@ static PyObject * PyKVIrc_internalWarning(PyObject * pSelf, PyObject * pArgs) static PyObject * PyKVIrc_error(PyObject * pSelf, PyObject * pArgs) { Q_UNUSED(pSelf); - const char * pcText=0; + const char * pcText = nullptr; if(QThread::currentThread() != g_pApp->thread()) { @@ -351,9 +336,7 @@ static PyObject * PyKVIrc_error(PyObject * pSelf, PyObject * pArgs) return 0; if(pcText) - { g_lError.append(pcText); - } return Py_BuildValue("i",1); } @@ -379,32 +362,35 @@ static PyMethodDef KVIrcMethods[] = { "" }, { "error", PyKVIrc_error, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } + { nullptr, nullptr, 0, nullptr } }; PyMODINIT_FUNC python_init() { - static void * PyKVIrc_API[PyKVIrc_API_NUM]; + static const PyCFunction PyKVIrc_API[] = { + PyKVIrc_echo, + PyKVIrc_say, + PyKVIrc_warning, + PyKVIrc_getLocal, + PyKVIrc_setLocal, + PyKVIrc_getGlobal, + PyKVIrc_setGlobal, + PyKVIrc_eval, + PyKVIrc_internalWarning, + PyKVIrc_error, + }; + PyObject * pModule; PyObject * pC_API_Object; - pModule = Py_InitModule("kvirc",KVIrcMethods); - if(!pModule) return; - - // Initialize the C API pointer array - PyKVIrc_API[0] = (void *)PyKVIrc_echo; - PyKVIrc_API[1] = (void *)PyKVIrc_say; - PyKVIrc_API[2] = (void *)PyKVIrc_warning; - PyKVIrc_API[3] = (void *)PyKVIrc_getLocal; - PyKVIrc_API[4] = (void *)PyKVIrc_setLocal; - PyKVIrc_API[5] = (void *)PyKVIrc_getGlobal; - PyKVIrc_API[6] = (void *)PyKVIrc_setGlobal; - PyKVIrc_API[7] = (void *)PyKVIrc_eval; - PyKVIrc_API[8] = (void *)PyKVIrc_internalWarning; - PyKVIrc_API[9] = (void *)PyKVIrc_error; + if(!(pModule = Py_InitModule3("kvirc", KVIrcMethods, nullptr))) + { + KVI_ASSERT("Python: Unable to initialize kvirc import module"); + return; + } // Create a CObject containing the API pointer array's address - pC_API_Object = PyCObject_FromVoidPtr((void *)PyKVIrc_API,NULL); + pC_API_Object = PyCObject_FromVoidPtr(const_cast<PyCFunction *>(PyKVIrc_API), nullptr); if(pC_API_Object) PyModule_AddObject(pModule,"_C_API",pC_API_Object); diff --git a/src/modules/pythoncore/kvircmodule.h b/src/modules/pythoncore/kvircmodule.h index 32b30e2f0..4fffacee4 100644 --- a/src/modules/pythoncore/kvircmodule.h +++ b/src/modules/pythoncore/kvircmodule.h @@ -54,25 +54,7 @@ PyMODINIT_FUNC python_init(); #ifdef __cplusplus extern "C" { #endif - - // Total number of C API pointers - #define PyKVIrc_API_NUM 10 - - #ifdef KVIRC_MODULE - // This section is used when compiling kvircmodule.cpp - #if 0 - PyObject * PyKVIrc_echo(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_say(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_warning(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_getLocal(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_setLocal(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_getGlobal(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_setGlobal(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_eval(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_internalWarning(PyObject * pSelf, PyObject * pArgs); - PyObject * PyKVIrc_error(PyObject * pSelf, PyObject * pArgs); - #endif - #else + #ifndef KVIRC_MODULE // This section is used in modules that use kvircmodule's API static void ** PyKVIrc_API; @@ -102,7 +84,7 @@ extern "C" { * In case on unsuccess, it sets the exception * \return int */ - static int import_kvirc() + inline static int import_kvirc() { PyObject * pModule = PyImport_ImportModule("kvirc"); if(pModule) diff --git a/src/modules/pythoncore/libkvipythoncore.cpp b/src/modules/pythoncore/libkvipythoncore.cpp index 1f125b626..b8e6c8e7b 100644 --- a/src/modules/pythoncore/libkvipythoncore.cpp +++ b/src/modules/pythoncore/libkvipythoncore.cpp @@ -22,121 +22,98 @@ // //============================================================================= +#include <functional> +#include <memory> +#include <unordered_map> +#include <utility> #include "kvi_settings.h" #include "KviModule.h" #include "KviLocale.h" -//#include "KviModuleManager.h" -//#include "KviFileUtils.h" -//#include "KviApplication.h" -//#include "KviOptions.h" -//#include "kvi_out.h" #ifdef COMPILE_PYTHON_SUPPORT - #include "kvircmodule.h" - #include "pythoncoreinterface.h" +#include "kvircmodule.h" +#include "pythoncoreinterface.h" - #include <Python.h> +#include <Python.h> -KviKvsRunTimeContext * g_pCurrentKvsContext = 0; +KviKvsRunTimeContext * g_pCurrentKvsContext = nullptr; bool g_bExecuteQuiet = false; QStringList g_lWarningList; QString g_lError; -static KviCString g_szLastReturnValue(""); -static PyThreadState * mainThreadState = NULL; +static PyThreadState * mainThreadState = nullptr; -class KviPythonInterpreter -{ -public: - KviPythonInterpreter(const QString & szContextName); - ~KviPythonInterpreter(); -protected: - QString m_szContextName; - PyThreadState * m_pThreadState; -public: - bool init(); // if this fails then well.. :D - void done(); - bool execute(const QString & szCode, QStringList & lArgs, QString & szRetVal, QString & szError, QStringList & lWarnings); - const QString & contextName() const { return m_szContextName; }; +struct KviPythonLock { + KviPythonLock(PyThreadState * ts) { + PyEval_RestoreThread(ts); + } + ~KviPythonLock() { + PyEval_SaveThread(); + } }; -KviPythonInterpreter::KviPythonInterpreter(const QString & szContextName) -{ - m_szContextName = szContextName; - m_pThreadState = 0; -} +struct KviPythonInterpreterDeleter { + void operator()(PyThreadState * ts) const + { + KviPythonLock lock{ts}; + Py_EndInterpreter(ts); + PyThreadState_Swap(mainThreadState); + } +}; -KviPythonInterpreter::~KviPythonInterpreter() -{ - done(); -} +struct KviPythonInterpreter { + KviPythonInterpreter(); + bool execute(QString, QStringList&, QString&, QString&, QStringList&); + std::unique_ptr<PyThreadState, KviPythonInterpreterDeleter> m_uptrThreadState; +}; + +struct KviCaseInsensitiveQStringHash { + std::size_t operator()(const QString& s) const + { + return static_cast<std::size_t>(qHash(s.toLower())); + } +}; -bool KviPythonInterpreter::init() +struct KviCaseInsensitiveQStringEqual { + bool operator()(const QString& s, const QString& t) const + { + return (s.toLower() == t.toLower()); + } +}; + +static std::unordered_map<QString,KviPythonInterpreter,KviCaseInsensitiveQStringHash,KviCaseInsensitiveQStringEqual> g_Interpreters; + +KviPythonInterpreter::KviPythonInterpreter() { -// get the global lock - PyEval_AcquireLock(); - // get a reference to the PyInterpreterState - PyInterpreterState * mainInterpreterState = mainThreadState->interp; - // create a thread state object for this thread - m_pThreadState = PyThreadState_New(mainInterpreterState); - // swap in the current thread state - PyThreadState_Swap(m_pThreadState); - // and hook in the kvirc error handling routines - QString szPreCode = QString( \ - "import kvirc\n" \ - "import sys\n" \ - "class kvirc_stderr_grabber:\n" \ - "\tdef write(self,s):\n" \ - "\t\tkvirc.error(s)\n" \ + KviPythonLock lock{mainThreadState}; + m_uptrThreadState.reset(Py_NewInterpreter()); + + python_init(); + + // hook in the kvirc error handling routines + QString szPreCode = QString( + "import kvirc\n" + "import sys\n" + "class kvirc_stderr_grabber:\n\tdef write(self,s):\n\t\tkvirc.error(s)\n" "sys.stderr=kvirc_stderr_grabber()\n" ); - // evaluate that - PyRun_SimpleString(szPreCode.toUtf8().data()); - // swap out our thread state for now - PyThreadState_Swap(NULL); - - // free the lock - PyEval_ReleaseLock(); - return true; -} -void KviPythonInterpreter::done() -{ - if(!m_pThreadState)return; - // grab the lock - PyEval_AcquireLock(); - // swap my thread state out of the interpreter - PyThreadState_Swap(NULL); - // clear out any cruft from thread state object - PyThreadState_Clear(m_pThreadState); - // delete my thread state object - PyThreadState_Delete(m_pThreadState); - // release the lock - PyEval_ReleaseLock(); - m_pThreadState = 0; + PyRun_SimpleString(szPreCode.toUtf8().data()); } -bool KviPythonInterpreter::execute( - const QString &szCode, - QStringList &lArgs, //args - QString &szRetVal, - QString &szError, - QStringList &) //lWarnings +bool KviPythonInterpreter::execute(QString szCode, QStringList& lArgs, + QString& szRetVal, QString& szError, QStringList&) { - if(!m_pThreadState) + if(!m_uptrThreadState) { szError = __tr2qs_ctx("Internal error: Python interpreter not initialized","python"); return false; } - int retVal; g_lError.clear(); - // grab the global interpreter lock - PyEval_AcquireLock(); - // swap in my thread state - PyThreadState_Swap(m_pThreadState); + KviPythonLock lock{m_uptrThreadState.get()}; QString szVarCode = "aArgs = ["; @@ -155,101 +132,72 @@ bool KviPythonInterpreter::execute( PyRun_SimpleString(szVarCode.toUtf8().data()); - //clean "cr" from the python code (ticket #1028) - QString szCleanCode = szCode; - szCleanCode.replace(QRegExp("\r\n?"), "\n"); - // execute some python code - retVal = PyRun_SimpleString(szCleanCode.toUtf8().data()); + // clean "cr" from the python code (ticket #1028) + szCode.replace(QRegExp("\r\n?"), "\n"); + + int retVal = PyRun_SimpleString(szCode.toUtf8().data()); szRetVal.setNum(retVal); - if (PyErr_Occurred() || retVal) - { + if(PyErr_Occurred() || retVal) szError = g_lError; - } - // clear the thread state - PyThreadState_Swap(NULL); - // release our hold on the global interpreter - PyEval_ReleaseLock(); - - if(retVal) - return false; - return true; + return !retVal; } - static KviPointerHashTable<QString,KviPythonInterpreter> * g_pInterpreters = 0; - -static KviPythonInterpreter * pythoncore_get_interpreter(const QString &szContextName) +static void pythoncore_destroy_interpreter(const QString& szContextName) { - KviPythonInterpreter * i = g_pInterpreters->find(szContextName); - if(i)return i; - i = new KviPythonInterpreter(szContextName); - if(!i->init()) - { - delete i; - return 0; - } - g_pInterpreters->replace(szContextName,i); - return i; -} + const auto i = g_Interpreters.find(szContextName); -static void pythoncore_destroy_interpreter(const QString &szContextName) -{ - KviPythonInterpreter * i = g_pInterpreters->find(szContextName); - if(!i)return; - g_pInterpreters->remove(szContextName); - i->done(); - delete i; + if(i != g_Interpreters.end()) + g_Interpreters.erase(i); } -static void pythoncore_destroy_all_interpreters() +#endif // COMPILE_PYTHON_SUPPORT + +template<typename T> +T * castFromModParam(void * p) { - KviPointerHashTableIterator<QString,KviPythonInterpreter> it(*g_pInterpreters); + T * ex = static_cast<T *>(p); - while(it.current()) - { - KviPythonInterpreter * i = it.current(); - i->done(); - delete i; - ++it; - } - g_pInterpreters->clear(); -} + if(ex->uSize != sizeof(T)) + return nullptr; -#endif // COMPILE_PYTHON_SUPPORT + return ex; +} static bool pythoncore_module_ctrl(KviModule *,const char * cmd,void * param) { #ifdef COMPILE_PYTHON_SUPPORT - if(kvi_strEqualCS(cmd,KVI_PYTHONCORECTRLCOMMAND_EXECUTE)) + if(!strcmp(cmd,KVI_PYTHONCORECTRLCOMMAND_EXECUTE)) { - KviPythonCoreCtrlCommand_execute * ex = (KviPythonCoreCtrlCommand_execute *)param; - if(ex->uSize != sizeof(KviPythonCoreCtrlCommand_execute))return false; - g_pCurrentKvsContext = ex->pKvsContext; - g_bExecuteQuiet = ex->bQuiet; - if(ex->szContext.isEmpty()) + auto * pex = castFromModParam<KviPythonCoreCtrlCommand_execute>(param); + + if(!pex) + return false; + + auto& ex = *pex; + + g_pCurrentKvsContext = ex.pKvsContext; + g_bExecuteQuiet = ex.bQuiet; + if(ex.szContext.isEmpty()) { - KviPythonInterpreter * m = new KviPythonInterpreter("temporary"); - if(!m->init()) - { - delete m; - return false; - } - ex->bExitOk = m->execute(ex->szCode,ex->lArgs,ex->szRetVal,ex->szError,ex->lWarnings); - m->done(); - delete m; + KviPythonInterpreter m; + ex.bExitOk = m.execute(ex.szCode,ex.lArgs,ex.szRetVal,ex.szError,ex.lWarnings); } else { - KviPythonInterpreter * m = pythoncore_get_interpreter(ex->szContext); - ex->bExitOk = m->execute(ex->szCode,ex->lArgs,ex->szRetVal,ex->szError,ex->lWarnings); + KviPythonInterpreter& m = g_Interpreters[ex.szContext]; + ex.bExitOk = m.execute(ex.szCode,ex.lArgs,ex.szRetVal,ex.szError,ex.lWarnings); } return true; } - if(kvi_strEqualCS(cmd,KVI_PYTHONCORECTRLCOMMAND_DESTROY)) + if(!strcmp(cmd,KVI_PYTHONCORECTRLCOMMAND_DESTROY)) { - KviPythonCoreCtrlCommand_destroy * de = (KviPythonCoreCtrlCommand_destroy *)param; - if(de->uSize != sizeof(KviPythonCoreCtrlCommand_destroy))return false; - pythoncore_destroy_interpreter(de->szContext); + auto * pde = castFromModParam<KviPythonCoreCtrlCommand_destroy>(param); + + if(!pde) + return false; + + pythoncore_destroy_interpreter(pde->szContext); return true; } #endif // COMPILE_PYTHON_SUPPORT @@ -259,63 +207,43 @@ static bool pythoncore_module_ctrl(KviModule *,const char * cmd,void * param) static bool pythoncore_module_init(KviModule *) { #ifdef COMPILE_PYTHON_SUPPORT - - // Initialize the Python interpreter Py_Initialize(); PyEval_InitThreads(); - // save a pointer to the main PyThreadState object - mainThreadState = PyThreadState_Get(); - // release the lock - PyEval_ReleaseLock(); + mainThreadState = PyEval_SaveThread(); - // Initialize the Python module for KVIrc - python_init(); + if(!g_Interpreters.empty()) + qDebug("libkvipythoncore: init(): Called init twice??"); - g_pInterpreters = new KviPointerHashTable<QString,KviPythonInterpreter>(17,false); - g_pInterpreters->setAutoDelete(false); return true; - #endif // COMPILE_PYTHON_SUPPORT - return false; } static bool pythoncore_module_cleanup(KviModule *) { #ifdef COMPILE_PYTHON_SUPPORT - pythoncore_destroy_all_interpreters(); - delete g_pInterpreters; - g_pInterpreters = 0; - - // shut down the interpreter - PyEval_AcquireLock(); - PyThreadState_Swap(mainThreadState); - PyEval_ReleaseLock(); - //FIXME currently python hangs forever on Py_Finalize() - //under win32/mingw; this is a (bad) workaround -#ifndef COMPILE_ON_MINGW + g_Interpreters.clear(); + PyEval_RestoreThread(mainThreadState); Py_Finalize(); -#endif //COMPILE_ON_MINGW - #endif // COMPILE_PYTHON_SUPPORT - return true; } static bool pythoncore_module_can_unload(KviModule *) { #ifdef COMPILE_PYTHON_SUPPORT - return (g_pInterpreters->count() == 0); + return g_Interpreters.empty(); #endif // COMPILE_PYTHON_SUPPORT return true; } KVIRC_MODULE( - "PythonCore", // module name + "PythonCore", // module name "4.0.0", // module version - "Copyright (C) 2008 Elvio Basello (hellvis69 at netsons dot org)\n" \ - "Copyright (C) 2009 Fabio Bas (ctrlaltca at libero dot it)", + "Copyright (C) 2008 Elvio Basello (hellvis69 at netsons dot org)\n" + "Copyright (C) 2009 Fabio Bas (ctrlaltca at libero dot it)\n" + "Copyright (C) 2016 Matt Ullman (staticfox at staticfox dot net)", "Python Scripting Engine Core", pythoncore_module_init, pythoncore_module_can_unload, |
