// Module : SALOME
// $Header$
-using namespace std;
-#include "PyInterp_base.h"
-#include "utilities.h"
#include <string>
#include <vector>
+
+#include <Python.h>
#include <cStringIO.h>
+#include <qmutex.h>
+
+#include "PyInterp_base.h"
+#include "utilities.h"
+
+
using namespace std;
-extern "C" PyObject * PyEval_EvalCode(PyObject *co, PyObject *g, PyObject *l);
-static PyThreadState *savedThreadState = NULL;
+#ifdef _DEBUG_
+static int MYDEBUG = 1;
+#else
+static int MYDEBUG = 0;
+#endif
-/*!
- * We have our own routines which are identical to the SIP routines
- * to not depend from SIP software evolutions
- */
+static QMutex myMutex;
-extern "C" void salomeAcquireLock()
+PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState):
+ myThreadState(theThreadState),
+ mySaveThreadState(PyInterp_base::_gtstate)
{
- MESSAGE("salomeAcquireLock");
- PyEval_RestoreThread(savedThreadState);
- savedThreadState = NULL;
-}
+ if(MYDEBUG) MESSAGE(" PyLockWrapper(...) - myThreadState = "<<myThreadState<<" - "<<myMutex.locked());
+ myMutex.lock();
+ PyEval_RestoreThread(myThreadState);
-extern "C" void salomeReleaseLock()
-{
- MESSAGE("salomeReleaseLock");
- savedThreadState = PyEval_SaveThread();
-}
+ //PyEval_AcquireLock();
+ //PyThreadState_Swap(myThreadState);
-extern "C" int salomeCondAcquireLock()
-{
- MESSAGE("salomeCondAcquireLock");
- if(savedThreadState != NULL)
- {
- /*
- * If savedThreadState is not NULL, Python global lock is not already acquired
- * We acquire it
- * and return 1 to the caller
- */
- salomeAcquireLock();
- //MESSAGE("We got it (the lock)");
- return 1;
- }
- /*
- * If savedThreadState is NULL, Python global lock is already acquired
- * We don't acquire or release it
- * We return 0 to the caller
- * CAUTION : it's only true when there is no event programming running (Tkinter, PyQt)
- */
- return 0;
-}
+ //PyEval_SaveThread();
-extern "C" void salomeCondReleaseLock(int rellock)
-{
- MESSAGE("salomeCondReleaseLock");
- if(rellock )
- salomeReleaseLock();
+ //mySaveThreadState = PyThreadState_Swap(myThreadState);
+ //PyEval_ReleaseLock();
}
-// main python interpreter
-PyThreadState *PyInterp_base::_gtstate=0; // force 0 before execution
-int PyInterp_base::_argc=1;
-char* PyInterp_base::_argv[] = {""};
+PyLockWrapper::~PyLockWrapper(){
+ if(MYDEBUG) MESSAGE("~PyLockWrapper(...) - myThreadState = "<<myThreadState);
+ PyEval_SaveThread();
+ myMutex.unlock();
-PyObject *PyInterp_base::builtinmodule=NULL;
-PyObject *PyInterp_base::salome_shared_modules_module=NULL;
+ //PyThreadState_Swap(NULL);
+ //PyEval_ReleaseLock();
-void init_python()
-{
- SCRUTE(PyInterp_base::_gtstate);
- if (PyInterp_base::_gtstate) return;
- Py_Initialize(); // Initialize the interpreter
- PyEval_InitThreads(); // Create (and acquire) the interpreter lock
- PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv); // initialize sys.argv
- PyInterp_base::_gtstate = PyThreadState_Get();
- SCRUTE(PyInterp_base::_gtstate);
+ //PyEval_RestoreThread(myThreadState);
- // /*
- // * Import __builtin__ module and store it to use it with all sub-interpreters
- // * This hack could be used with event programming (PyQt) to avoid errors
- // * encountered with incoherent builtins
- // */
+ //PyEval_AcquireLock();
+ //PyThreadState_Swap(mySaveThreadState);
+}
- // PyInterp_base::builtinmodule =PyImport_ImportModule("__builtin__");
- // SCRUTE(PyInterp_base::builtinmodule->ob_refcnt);
- /*
- * Import salome_shared_modules module and store it to use it with all sub-interpreters
- */
+class PyReleaseLock{
+public:
+ ~PyReleaseLock(){
+ if(MYDEBUG) MESSAGE("~PyReleaseLock()");
+ //PyEval_SaveThread();
- PyInterp_base::salome_shared_modules_module =PyImport_ImportModule("salome_shared_modules");
- if(PyInterp_base::salome_shared_modules_module == NULL){
- MESSAGE("init_python: problem with salome_shared_modules import");
- PyErr_Print();
- PyErr_Clear();
- salomeReleaseLock();
- return;
+ PyEval_ReleaseLock();
}
- SCRUTE(PyInterp_base::salome_shared_modules_module->ob_refcnt);
- salomeReleaseLock();
+};
+
+
+PyLockWrapper PyInterp_base::GetLockWrapper(){
+ return PyLockWrapper(_tstate);
}
+// main python interpreter
+
+PyThreadState *PyInterp_base::_gtstate = 0; // force 0 before execution
+int PyInterp_base::_argc = 1;
+char* PyInterp_base::_argv[] = {""};
+
+PyObject *PyInterp_base::builtinmodule = NULL;
+PyObject *PyInterp_base::salome_shared_modules_module = NULL;
+
/*!
* This function compiles a string (command) and then evaluates it in the dictionnary
* context if possible.
* 1 : incomplete text
* 0 : complete text executed with success
*/
-
int compile_command(const char *command,PyObject *context)
{
- SCRUTE(command);
- PyObject *m,*v,*r;
-
- m=PyImport_AddModule("codeop");
- if(m == NULL)
- {
- /*
- * Fatal error. No way to go on.
- */
+ PyObject *m = PyImport_AddModule("codeop");
+ if(!m){ // Fatal error. No way to go on.
+ PyErr_Print();
+ return -1;
+ }
+ PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
+ if(!v){
+ // Error encountered. It should be SyntaxError,
+ //so we don't write out traceback
+ PyObjWrapper exception, value, tb;
+ PyErr_Fetch(&exception, &value, &tb);
+ PyErr_NormalizeException(&exception, &value, &tb);
+ PyErr_Display(exception, value, NULL);
+ return -1;
+ }else if (v == Py_None){
+ // Incomplete text we return 1 : we need a complete text to execute
+ return 1;
+ }else{
+ // Complete and correct text. We evaluate it.
+ PyObjWrapper r(PyEval_EvalCode(v,context,context));
+ if(!r){
+ // Execution error. We return -1
PyErr_Print();
return -1;
}
- v= PyObject_CallMethod(m,"compile_command","s",command);
- if (v == NULL)
- {
- /*
- * Error encountered. It should be SyntaxError
- * so we don't write out traceback
- */
- PyObject *exception,*value,*tb;
- PyErr_Fetch(&exception, &value, &tb);
- PyErr_NormalizeException(&exception, &value, &tb);
- PyErr_Display(exception, value, NULL);
- Py_XDECREF(exception);
- Py_XDECREF(value);
- Py_XDECREF(tb);
-
- return -1;
- }
- else if (v == Py_None)
- {
- /*
- * Incomplete text we return 1 : we need a complete text to execute
- */
- return 1;
- }
- else
- {
- /*
- * Complete and correct text. We evaluate it.
- */
- r = PyEval_EvalCode(v,context,context);
- Py_DECREF(v);
- if (r==NULL)
- {
- /*
- * Execution error. We return -1
- */
- PyErr_Print();
- return -1;
- }
- Py_DECREF(r);
- /*
- * The command has been successfully executed. Return 0
- */
- return 0;
- }
+ // The command has been successfully executed. Return 0
+ return 0;
+ }
}
+
/*!
* basic constructor here : herited classes constructors must call initalize() method
* defined here.
*/
-
-PyInterp_base::PyInterp_base():_tstate(0),_vout(0),_verr(0),_g(0),_atFirst(true)
+PyInterp_base::PyInterp_base(): _tstate(0), _vout(0), _verr(0), _g(0), _atFirst(true)
{
MESSAGE("PyInterp_base::PyInterp_base()");
}
PyInterp_base::~PyInterp_base()
{
MESSAGE("PyInterp_base::~PyInterp_base()");
- salomeAcquireLock();
+ PyLockWrapper aLock(_tstate);
PyThreadState_Swap(_tstate);
Py_EndInterpreter(_tstate);
- salomeReleaseLock();
}
+
+void init_python()
+{
+ if(MYDEBUG) MESSAGE("init_python()");
+ if (PyInterp_base::_gtstate) return;
+ Py_Initialize(); // Initialize the interpreter
+
+ PyEval_InitThreads(); // Initialize and acquire the global interpreter lock
+
+ PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv); // initialize sys.argv
+ PyInterp_base::_gtstate = PyThreadState_Get();
+ if(MYDEBUG) SCRUTE(PyInterp_base::_gtstate);
+
+ PyInterp_base::salome_shared_modules_module = PyImport_ImportModule("salome_shared_modules");
+ if(!PyInterp_base::salome_shared_modules_module){
+ MESSAGE("init_python: problem with salome_shared_modules import");
+ PyErr_Print();
+ PyErr_Clear();
+ }else{
+ if(MYDEBUG) SCRUTE(PyInterp_base::salome_shared_modules_module->ob_refcnt);
+ }
+}
+
+
/*!
* Must be called by herited classes constructors. initialize() calls virtuals methods
* initstate & initcontext, not defined here in base class. initstate & initcontext methods
*/
void PyInterp_base::initialize()
{
- MESSAGE("PyInterp_base::initialize()");
- PyObject *m,*v,*c;
-
+ if(MYDEBUG) MESSAGE("PyInterp_base::initialize()");
_history.clear(); // start a new list of user's commands
_ith = _history.begin();
+ PyReleaseLock aReleaseLock;
init_python();
+ //PyLockWrapper aLock(_tstate);
initState();
-
initContext();
- m=PyImport_ImportModule("codeop"); // used to interpret & compile commands
- if(m == NULL)
- {
- MESSAGE("Problem...");
- PyErr_Print();
- ASSERT(0);
- salomeReleaseLock();
- return;
- }
- Py_DECREF(m);
+ // used to interpret & compile commands
+ PyObjWrapper m(PyImport_ImportModule("codeop"));
+ if(!m){
+ if(MYDEBUG) MESSAGE("Problem...");
+ PyErr_Print();
+ ASSERT(0);
+ return;
+ }
- /*
- * Create cStringIO to capture stdout and stderr
- */
+ // Create cStringIO to capture stdout and stderr
//PycString_IMPORT;
- PycStringIO=(PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
- _vout=PycStringIO->NewOutput(128);
- _verr=PycStringIO->NewOutput(128);
+ PycStringIO = (PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
+ _vout = PycStringIO->NewOutput(128);
+ _verr = PycStringIO->NewOutput(128);
// All the initRun outputs are redirected to the standard output (console)
- this->initRun();
+ initRun();
// We go out of Python world to enter the C++ world. Release the Python global lock
- salomeReleaseLock();
- SCRUTE(_tstate);
- SCRUTE(this);
+ if(MYDEBUG) SCRUTE(_tstate);
}
string PyInterp_base::getbanner()
{
- MESSAGE("PyInterp_base::getbanner()");
- string banner = "Python ";
- banner = banner + Py_GetVersion() + " on " + Py_GetPlatform() ;
- banner = banner + "\ntype help to get general information on environment\n";
- return banner.c_str();
+ string aBanner("Python ");
+ aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
+ aBanner = aBanner + "\ntype help to get general information on environment\n";
+ return aBanner;
}
+
int PyInterp_base::initRun()
{
- MESSAGE("PyInterp_base::initRun()");
+ if(MYDEBUG) MESSAGE("PyInterp_base::initRun()");
PySys_SetObject("stderr",_verr);
PySys_SetObject("stdout",_vout);
- PyObject *v = PyObject_CallMethod(_verr,"reset","");
- Py_XDECREF(v);
- v = PyObject_CallMethod(_vout,"reset","");
- Py_XDECREF(v);
+ PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
+ PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
-
- PyObject *m;
- m = PyImport_GetModuleDict();
+ PyObject *m = PyImport_GetModuleDict();
PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
- MESSAGE(this->getvout());
- MESSAGE(this->getverr());
-
return 0;
}
-void PyInterp_base::enter()
-{
- MESSAGE("PyInterp_base::enter()");
- salomeAcquireLock();
- PyThreadState_Swap(_tstate);
-}
-
-void PyInterp_base::quit()
-{
- MESSAGE("PyInterp_base::quit()");
- salomeReleaseLock();
-}
-
-void PyInterp_base::basicRun(const char *command)
-{
- SCRUTE(command);
- PyObject *code,*r;
- enter();
- code=Py_CompileString((char *)command,"PyInterp_base",Py_file_input);
- if (code == NULL)
- {
- /*
- * Caught an error : SyntaxError
- * Print it and quit
- */
- PyErr_Print();
- quit();
- return;
- }
- r = PyEval_EvalCode(code,_g,_g);
- Py_DECREF(code);
- if (r==NULL)
- {
- /*
- * Caught an error during execution
- * Print it and quit
- */
- PyErr_Print();
- quit();
- return;
- }
- Py_DECREF(r);
- quit();
-}
int PyInterp_base::run(const char *command)
{
- SCRUTE(command);
- int ret = 0;
- if (_atFirst)
- {
- _atFirst = false;
- ret = this->simpleRun("from Help import *");
- MESSAGE(this->getvout())
- MESSAGE(this->getverr())
- if (ret != 0) return ret;
- ret = this->simpleRun("import salome");
- MESSAGE(this->getvout());
- MESSAGE(this->getverr())
- if (ret != 0) return ret;
- }
- ret = this->simpleRun(command);
- return ret;
+ if(_atFirst){
+ int ret = 0;
+ _atFirst = false;
+ ret = simpleRun("from Help import *");
+ if (ret) return ret;
+ ret = simpleRun("import salome");
+ if (ret) return ret;
+ }
+ return simpleRun(command);
}
+
int PyInterp_base::simpleRun(const char *command)
{
- SCRUTE(command);
- PyObject *v,*m,*r,*g;
- char *output;
- int ier=0;
- string s_com = command;
-
- if (s_com.size() > 0)
- {
- _history.push_back(s_com);
- _ith = _history.end();
- SCRUTE(_history.back());
- }
+ if(MYDEBUG) MESSAGE("simpleRun(...) - command = '"<<command<<"'");
+ if(strcmp(command,"") != 0){
+ _history.push_back(command);
+ _ith = _history.end();
+ }
- // SCRUTE(this);
- // SCRUTE(_tstate);
// We come from C++ to enter Python world
// We need to acquire the Python global lock
- salomeAcquireLock();
- // Restore the sub interpreter thread state : this._tstate
- PyThreadState_Swap(_tstate);
+ PyLockWrapper aLock(_tstate);
- /*
- Reset redirected outputs before treatment
- */
+ // Reset redirected outputs before treatment
PySys_SetObject("stderr",_verr);
PySys_SetObject("stdout",_vout);
-
- v = PyObject_CallMethod(_verr,"reset","");
- Py_XDECREF(v);
- v = PyObject_CallMethod(_vout,"reset","");
- Py_XDECREF(v);
+
+ PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
+ PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
- ier=compile_command(command,_g);
+ int ier = compile_command(command,_g);
// Outputs are redirected on standards outputs (console)
PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
-
- // We go back to the C++ world. Release the lock.
- salomeReleaseLock();
return ier;
}
-static string vout_buffer;
-static string verr_buffer;
-
-char * PyInterp_base::getverr()
-{
- MESSAGE("PyInterp_base::getverr");
- PyObject *v;
- v=PycStringIO->cgetvalue(_verr);
- verr_buffer=PyString_AsString(v);
- Py_DECREF(v);
- return (char *)verr_buffer.c_str();
-}
-char * PyInterp_base::getvout()
-{
- MESSAGE("PyInterp_base::getvout");
- PyObject *v;
- v=PycStringIO->cgetvalue(_vout);
- vout_buffer=PyString_AsString(v);
- Py_DECREF(v);
- return (char *)vout_buffer.c_str();
-}
-
const char * PyInterp_base::getPrevious()
{
- MESSAGE("PyInterp_base::getPrevious");
- if (_ith != _history.begin())
- {
- _ith--;
- return (*_ith).c_str();
- }
+ if(_ith != _history.begin()){
+ _ith--;
+ return (*_ith).c_str();
+ }
else
return BEGIN_HISTORY_PY;
}
+
const char * PyInterp_base::getNext()
{
- MESSAGE("PyInterp_base::getNext");
- if (_ith != _history.end())
- {
- _ith++;
- }
+ if(_ith != _history.end()){
+ _ith++;
+ }
if (_ith == _history.end())
return TOP_HISTORY_PY;
else
return (*_ith).c_str();
}
+
+
+string PyInterp_base::getverr(){
+ //PyLockWrapper aLock(_tstate);
+ PyObjWrapper v(PycStringIO->cgetvalue(_verr));
+ string aRet(PyString_AsString(v));
+ return aRet;
+}
+
+
+string PyInterp_base::getvout(){
+ //PyLockWrapper aLock(_tstate);
+ PyObjWrapper v(PycStringIO->cgetvalue(_vout));
+ string aRet(PyString_AsString(v));
+ return aRet;
+}
+