From f70bcc7d7b9bc71bd91e82899868bbc2f3fcd34d Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Thu, 24 Sep 2009 18:12:47 +0000 Subject: some work on python module git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@3524 17fca916-40b9-46aa-a4ea-0a15b648b75c --- src/modules/pythoncore/libkvipythoncore.cpp | 220 ++++++++++++++++++++++----- src/modules/pythoncore/pythoncoreinterface.h | 11 +- 2 files changed, 195 insertions(+), 36 deletions(-) (limited to 'src/modules/pythoncore') diff --git a/src/modules/pythoncore/libkvipythoncore.cpp b/src/modules/pythoncore/libkvipythoncore.cpp index 49cfac429..37fa88dc0 100644 --- a/src/modules/pythoncore/libkvipythoncore.cpp +++ b/src/modules/pythoncore/libkvipythoncore.cpp @@ -37,54 +37,196 @@ #include "pythoncoreinterface.h" #include -/* - class KviPythonInterpreter +static KviKvsRunTimeContext * g_pCurrentKvsContext = 0; +static bool g_bExecuteQuiet = false; +static KviStr g_szLastReturnValue(""); +static QStringList g_lWarningList; + +static PyThreadState * mainThreadState = NULL; + +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(){ return m_szContextName; }; +}; + +KviPythonInterpreter::KviPythonInterpreter(const QString & szContextName) +{ + m_szContextName = szContextName; + m_pThreadState = 0; +} + +KviPythonInterpreter::~KviPythonInterpreter() +{ + done(); +} + +bool KviPythonInterpreter::init() +{ +// 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); + // 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; +} + +bool KviPythonInterpreter::execute( + const QString &szCode, + QStringList &args, + QString &szRetVal, + QString &szError, + QStringList &lWarnings) +{ + if(!m_pThreadState) { - public: - KviPythonInterpreter(const QString & szContextName); - ~KviPythonInterpreter(); - protected: - QString m_szContextName; - //PerlInterpreter * m_pInterpreter; - 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(){ return m_szContextName; }; - //protected: - // QString svToQString(SV * sv); - }; - - KviPythonInterpreter::KviPythonInterpreter(const QString & szContextName) + szError = __tr2qs_ctx("Internal error: python interpreter not initialized","python"); + return false; + } + + // grab the global interpreter lock + PyEval_AcquireLock(); + // swap in my thread state + PyThreadState_Swap(m_pThreadState); + // execute some python code + PyRun_SimpleString("import sys\n"); + PyRun_SimpleString("sys.stdout.write('Hello from a C thread!\\n')\n"); + // clear the thread state + PyThreadState_Swap(NULL); + // release our hold on the global interpreter + PyEval_ReleaseLock(); + + return true; +} + + static KviPointerHashTable * g_pInterpreters = 0; + +static KviPythonInterpreter * pythoncore_get_interpreter(const QString &szContextName) +{ + KviPythonInterpreter * i = g_pInterpreters->find(szContextName); + if(i)return i; + i = new KviPythonInterpreter(szContextName); + if(!i->init()) { - m_szContextName = szContextName; - //m_pInterpreter = 0; + delete i; + return 0; } + g_pInterpreters->replace(szContextName,i); + return i; +} - KviPythonInterpreter::~KviPythonInterpreter() +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; +} + +static void pythoncore_destroy_all_interpreters() +{ + KviPointerHashTableIterator it(*g_pInterpreters); + + while(it.current()) + { + KviPythonInterpreter * i = it.current(); + i->done(); + delete i; + ++it; + } + g_pInterpreters->clear(); +} + +#endif // COMPILE_PYTHON_SUPPORT + +static bool pythoncore_module_ctrl(KviModule *,const char * cmd,void * param) +{ +#ifdef COMPILE_PYTHON_SUPPORT + if(kvi_strEqualCS(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()) + { + 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; + } else { + KviPythonInterpreter * m = pythoncore_get_interpreter(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)) { - done(); + KviPythonCoreCtrlCommand_destroy * de = (KviPythonCoreCtrlCommand_destroy *)param; + if(de->uSize != sizeof(KviPythonCoreCtrlCommand_destroy))return false; + pythoncore_destroy_interpreter(de->szContext); + return true; } -*/ #endif // COMPILE_PYTHON_SUPPORT + return false; +} static bool pythoncore_module_init(KviModule *) { #ifdef COMPILE_PYTHON_SUPPORT // Initialize the Python interpreter - debug("Initializing Python interpreter"); #ifdef COMPILE_ON_MAC PyMac_Initialize(); #else Py_Initialize(); #endif + PyEval_InitThreads(); + + // save a pointer to the main PyThreadState object + mainThreadState = PyThreadState_Get(); + // release the lock + PyEval_ReleaseLock(); // Initialize the Python module for KVIrc - python_init(); +// python_init(); - //g_pInterpreters = new KviPointerHashTable(17,false); - //g_pInterpreters->setAutoDelete(false); + g_pInterpreters = new KviPointerHashTable(17,false); + g_pInterpreters->setAutoDelete(false); return true; #endif // COMPILE_PYTHON_SUPPORT @@ -95,11 +237,12 @@ static bool pythoncore_module_init(KviModule *) static bool pythoncore_module_cleanup(KviModule *) { #ifdef COMPILE_PYTHON_SUPPORT - //perlcore_destroy_all_interpreters(); - //delete g_pInterpreters; - //g_pInterpreters = 0; + pythoncore_destroy_all_interpreters(); + delete g_pInterpreters; + g_pInterpreters = 0; - // Free the memory used by the Python interpreter + // shut down the interpreter + PyEval_AcquireLock(); Py_Finalize(); // Close the intepreter @@ -109,13 +252,22 @@ static bool pythoncore_module_cleanup(KviModule *) return true; } +static bool pythoncore_module_can_unload(KviModule *) +{ +#ifdef COMPILE_PYTHON_SUPPORT + return (g_pInterpreters->count() == 0); +#endif // COMPILE_PYTHON_SUPPORT + return true; +} + KVIRC_MODULE( "PythonCore", // module name "4.0.0", // module version - "Copyright (C) 2008 Elvio Basello (hellvis69 at netsons dot org", // author & (C) + "Copyright (C) 2008 Elvio Basello (hellvis69 at netsons dot org)\n" \ + "Copyright (C) 2009 Fabio Bas (ctrlaltca at libero dot it)", "Python Scripting Engine Core", pythoncore_module_init, - 0, - 0, + pythoncore_module_can_unload, + pythoncore_module_ctrl, pythoncore_module_cleanup ) diff --git a/src/modules/pythoncore/pythoncoreinterface.h b/src/modules/pythoncore/pythoncoreinterface.h index f09fde948..3463ce28b 100644 --- a/src/modules/pythoncore/pythoncoreinterface.h +++ b/src/modules/pythoncore/pythoncoreinterface.h @@ -1,5 +1,6 @@ #ifndef _PYTHONCOREINTERFACE_H_ #define _PYTHONCOREINTERFACE_H_ + //============================================================================= // // File : pythoncoreinterface.h @@ -20,7 +21,7 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, -// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= @@ -30,10 +31,14 @@ #include + +#define KVI_PYTHONCORECTRLCOMMAND_EXECUTE "execute" + typedef struct _KviPythonCoreCtrlCommand_execute { unsigned int uSize; KviKvsRunTimeContext * pKvsContext; + QString szContext; QString szCode; bool bExitOk; QString szRetVal; @@ -43,10 +48,12 @@ typedef struct _KviPythonCoreCtrlCommand_execute bool bQuiet; } KviPythonCoreCtrlCommand_execute; +#define KVI_PYTHONCORECTRLCOMMAND_DESTROY "destroy" + typedef struct _KviPythonCoreCtrlCommand_destroy { unsigned int uSize; QString szContext; } KviPythonCoreCtrlCommand_destroy; -#endif // _PYTHONCOREINTERFACE_H_ +#endif // !_PYTHONCOREINTERFACE_H_ -- cgit v1.3.1-10-gc9f91