lib_LTLIBRARIES = libPyInterp.la
-salomeinclude_HEADERS= \
- PyInterp.h \
- PyInterp_base.h \
+salomeinclude_HEADERS= \
+ PyInterp.h \
+ PyInterp_Interp.h \
PyInterp_Dispatcher.h
-dist_libPyInterp_la_SOURCES= \
- PyInterp_base.cxx \
+dist_libPyInterp_la_SOURCES= \
+ PyInterp_Interp.cxx \
PyInterp_Dispatcher.cxx
MOC_FILES= PyInterp_Watcher_moc.cxx
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-#if !defined ( _PYINTERP_H )
-#define _PYINTERP_H
+// File : PyInterp.h
+// Author : Vadim SANDLER
+// Module : SALOME
+
+#if !defined ( PYINTERP_H )
+#define PYINTERP_H
// ========================================================
// set dllexport type for Win platform
-#ifdef WNT
-
-#ifdef PYINTERP_EXPORTS
-#define PYINTERP_EXPORT __declspec(dllexport)
-#else
-#define PYINTERP_EXPORT __declspec(dllimport)
-#endif
-
-#else // WNT
-
-#define PYINTERP_EXPORT
-
-#endif // WNT
+#ifdef WIN32
+# ifdef PYINTERP_EXPORTS
+# define PYINTERP_EXPORT __declspec(dllexport)
+# else
+# define PYINTERP_EXPORT __declspec(dllimport)
+# endif
+#else // WIN32
+# define PYINTERP_EXPORT
+#endif // WIN32
// ========================================================
// little trick - if we do not have debug python libraries
// ========================================================
// avoid warning messages
-#ifdef WNT
+#ifdef WIN32
#pragma warning (disable : 4786)
#pragma warning (disable : 4251)
#endif
-#endif // _PYINTERP_H
+#endif // PYINTERP_H
--- /dev/null
+TEMPLATE = lib
+TARGET = PyInterp
+DESTDIR = ../../lib
+MOC_DIR = ../../moc
+OBJECTS_DIR = ../../obj/$$TARGET
+
+PYTHONVER=2.4
+PYTHONHOME=$$(PYTHONHOME)
+PYTHONINC=$${PYTHONHOME}/include/python$${PYTHONVER}
+PYTHONLIB=$${PYTHONHOME}/lib
+
+INCLUDEPATH += ../../include $${PYTHONINC}
+unix:LIBS += -L$${PYTHONLIB} -lpython$${PYTHONVER}
+win32:LIBS += /LIBPATH:$${PYTHONLIB}
+
+CONFIG -= debug release debug_and_release
+CONFIG += qt thread debug dll shared
+
+win32:DEFINES += WIN32
+DEFINES += PYINTERP_EXPORTS
+
+HEADERS = PyInterp.h
+HEADERS += PyInterp_Dispatcher.h
+HEADERS += PyInterp_Watcher.h
+HEADERS += PyInterp_Interp.h
+
+SOURCES = PyInterp_Dispatcher.cxx
+SOURCES += PyInterp_Interp.cxx
+
+includes.files = $$HEADERS
+includes.path = ../../include
+
+INSTALLS += includes
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
// File : PyInterp_Dispatcher.cxx
// Author : Sergey ANIKIN, OCC
// Module : GUI
-// $Header$
-
-#include <PyInterp_base.h>
-#include <PyInterp_Dispatcher.h>
-#include <PyInterp_Watcher.h>
+#include "PyInterp_Dispatcher.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+#include "PyInterp_Interp.h"
+#include "PyInterp_Watcher.h"
-#include <qapplication.h>
-#include <qobject.h>
+#include <QObject>
+#include <QCoreApplication>
-//#include <utilities.h>
using namespace std;
PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
{
safeExecute();
- myMutex.lock();
- //if ( !IsSync() && getListener() && getEvent() )
- if ( getListener() && getEvent() )
- postEvent();
- myMutex.unlock();
+ bool isSync = IsSync();
+
+ if ( !isSync )
+ myMutex.lock();
+
+ if ( listener() )
+ processEvent( listener() );
+
+ if ( !isSync )
+ myMutex.unlock();
}
void PyInterp_Request::safeExecute()
return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this );
}
-QEvent* PyInterp_Request::getEvent()
+void PyInterp_Request::processEvent( QObject* o )
{
- //if ( !myEvent && !IsSync() )
- if ( !myEvent )
- myEvent = createEvent();
- return myEvent;
-}
+ if ( !o )
+ return;
-void PyInterp_Request::postEvent()
-{
-#if QT_VERSION >= 0x030303
-// MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3")
- QApplication::postEvent( getListener(), getEvent() );
-#else
-// MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5")
- QThread::postEvent( getListener(), getEvent() );
-#endif
+ QEvent* e = createEvent();
+ if ( !e )
+ return;
+
+ if ( !IsSync() )
+ QCoreApplication::postEvent( o, e );
+ else
+ {
+ QCoreApplication::sendEvent( o, e );
+ delete e;
+ }
}
void PyInterp_Request::setListener( QObject* o )
// Clear the request queue
myQueueMutex.lock();
- for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
- PyInterp_Request::Destroy( *it );
+ QListIterator<RequestPtr> it( myQueue );
+ while ( it.hasNext() )
+ PyInterp_Request::Destroy( it.next() );
myQueue.clear();
myQueueMutex.unlock();
bool PyInterp_Dispatcher::IsBusy() const
{
- return running();
+ return isRunning();
}
void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
//if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
if ( theRequest->IsSync() ) // synchronous processing - nothing is done if dispatcher is busy!
processRequest( theRequest );
- else { // asynchronous processing
+ else // asynchronous processing
+ {
myQueueMutex.lock();
- myQueue.push_back( theRequest );
- if ( theRequest->getListener() )
- QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
+ myQueue.enqueue( theRequest );
+ if ( theRequest->listener() )
+ QObject::connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
myQueueMutex.unlock();
if ( !IsBusy() )
while( myQueue.size() ) {
// MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
- aRequest = myQueue.front();
+ aRequest = myQueue.head();
// let other threads append their requests to the end of the queue
myQueueMutex.unlock();
// prepare for removal of the first request in the queue
myQueueMutex.lock();
// IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
- if ( myQueue.front() == aRequest ) // It's still here --> remove it
- myQueue.pop_front();
+ if ( myQueue.head() == aRequest ) // It's still here --> remove it
+ myQueue.dequeue();
// MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
}
// prepare for modification of the queue
myQueueMutex.lock();
- for ( std::list<RequestPtr>::iterator it = myQueue.begin(); it != myQueue.end(); ++it ){
- if ( o == (*it)->getListener() ){
- (*it)->setListener( 0 ); // to prevent event posting
- it = myQueue.erase( it );
+ QMutableListIterator<RequestPtr> it( myQueue );
+ while ( it.hasNext() )
+ {
+ RequestPtr r = it.next();
+ if ( o == r->listener() )
+ {
+ r->setListener( 0 ); // to prevent event posting
+ it.remove();
}
}
myQueueMutex.unlock();
}
-
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
// File : PyInterp_Dispatcher.h
// Author : Sergey Anikin, OCC
// Module : SALOME
-#ifndef _PYINTERP_DISPATCHER_H_
-#define _PYINTERP_DISPATCHER_H_
-
-#include "PyInterp.h"
+#ifndef PYINTERP_DISPATCHER_H
+#define PYINTERP_DISPATCHER_H
-#include <qthread.h>
-#include <qevent.h>
+#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include <list>
+#include <QMutex>
+#include <QThread>
+#include <QEvent>
+#include <QQueue>
class QObject;
-class PyInterp_base;
+class PyInterp_Interp;
class PyInterp_Watcher;
class PyInterp_Dispatcher;
PyInterp_Request( const PyInterp_Request& );
protected:
- virtual ~PyInterp_Request() {};
+ virtual ~PyInterp_Request() {};
// protected destructor - to control deletion of requests
public:
PyInterp_Request( QObject* listener, bool sync = false )
- : myIsSync( sync ), myListener( listener ), myEvent( 0 ) {};
+ : myIsSync( sync ), myListener( listener ) {};
static void Destroy( PyInterp_Request* );
// Deletes a request
virtual QEvent* createEvent() const;
// This method can be overridden to customize notification event creation
+ virtual void processEvent( QObject* );
+
private:
void process();
- QObject* getListener() const { return myListener; }
+ QObject* listener() const { return myListener; }
void setListener( QObject* );
- QEvent* getEvent();
- void postEvent();
private:
+ QMutex myMutex;
bool myIsSync;
QObject* myListener;
- QEvent* myEvent;
- QMutex myMutex;
};
class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request
{
public:
- PyInterp_LockRequest( PyInterp_base* interp, QObject* listener = 0, bool sync = false )
+ PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener = 0, bool sync = false )
: PyInterp_Request( listener, sync ), myInterp( interp ) {}
protected:
- PyInterp_base* getInterp() const { return myInterp; }
+ PyInterp_Interp* getInterp() const { return myInterp; }
- virtual void safeExecute();
+ virtual void safeExecute();
private:
- PyInterp_base* myInterp;
+ PyInterp_Interp* myInterp;
};
-class PYINTERP_EXPORT PyInterp_Event : public QCustomEvent
+class PYINTERP_EXPORT PyInterp_Event : public QEvent
{
PyInterp_Event();
PyInterp_Event( const PyInterp_Event& );
enum { NOTIFY = QEvent::User + 5000, OK, ERROR, INCOMPLETE, LAST };
PyInterp_Event( int type, PyInterp_Request* request )
- : QCustomEvent( (QEvent::Type)type ), myRequest( request ) {}
+ : QEvent( (QEvent::Type)type ), myRequest( request ) {}
virtual ~PyInterp_Event();
private:
typedef PyInterp_Request* RequestPtr;
- std::list<RequestPtr> myQueue;
+ QQueue<RequestPtr> myQueue;
QMutex myQueueMutex;
PyInterp_Watcher* myWatcher;
friend class PyInterp_Watcher;
};
-#endif
+#endif // PYINTERP_DISPATCHER_H
--- /dev/null
+// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : PyInterp_Interp.cxx
+// Author : Christian CAREMOLI, Paul RASCLE, EDF
+// Module : SALOME
+
+#include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+
+#include <cStringIO.h>
+
+#include <string>
+#include <vector>
+
+using namespace std;
+
+#define TOP_HISTORY_PY "--- top of history ---"
+#define BEGIN_HISTORY_PY "--- begin of history ---"
+
+PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState):
+ myThreadState(theThreadState),
+ mySaveThreadState(0)
+{
+ if (myThreadState->interp == PyInterp_Interp::_interp)
+ _savestate = PyGILState_Ensure();
+ else
+ PyEval_AcquireThread(myThreadState);
+}
+
+PyLockWrapper::~PyLockWrapper()
+{
+ if (myThreadState->interp == PyInterp_Interp::_interp)
+ PyGILState_Release(_savestate);
+ else
+ PyEval_ReleaseThread(myThreadState);
+}
+
+PyLockWrapper PyInterp_Interp::GetLockWrapper()
+{
+ return _tstate;
+}
+
+/*!
+ \class PyInterp_Interp
+ \brief Generic embedded Python interpreter.
+*/
+
+int PyInterp_Interp::_argc = 1;
+char* PyInterp_Interp::_argv[] = {""};
+PyObject* PyInterp_Interp::builtinmodule = NULL;
+PyThreadState* PyInterp_Interp::_gtstate = NULL;
+PyInterpreterState* PyInterp_Interp::_interp = NULL;
+
+/*!
+ \brief Basic constructor.
+
+ After construction the interpreter instance successor classes
+ must call virtual method initalize().
+*/
+PyInterp_Interp::PyInterp_Interp():
+ _tstate(0), _vout(0), _verr(0), _g(0)
+{
+}
+
+/*!
+ \brief Destructor.
+*/
+PyInterp_Interp::~PyInterp_Interp()
+{
+}
+
+/*!
+ \brief Initialize embedded interpreter.
+
+ This method shoud be called after construction of the interpreter.
+ The method initialize() calls virtuals methods
+ - initPython() to initialize global Python interpreter
+ - initState() to initialize embedded interpreter state
+ - initContext() to initialize interpreter internal context
+ - initRun() to prepare interpreter for running commands
+ which should be implemented in the successor classes, according to the
+ embedded Python interpreter policy (mono or multi interpreter, etc).
+*/
+void PyInterp_Interp::initialize()
+{
+ _history.clear(); // start a new list of user's commands
+ _ith = _history.begin();
+
+ initPython();
+ // Here the global lock is released
+
+ initState();
+
+ PyLockWrapper aLock = GetLockWrapper();
+
+ initContext();
+
+ // used to interpret & compile commands
+ PyObjWrapper m(PyImport_ImportModule("codeop"));
+ if(!m) {
+ PyErr_Print();
+ return;
+ }
+
+ // Create cStringIO to capture stdout and stderr
+ PycString_IMPORT;
+ if (PycStringIO) { // CTH11627 : additional check
+ _vout = PycStringIO->NewOutput(128);
+ _verr = PycStringIO->NewOutput(128);
+ }
+
+ // All the initRun outputs are redirected to the standard output (console)
+ initRun();
+}
+
+/*!
+ \brief Initialize Python interpreter.
+
+ Set program name, initialize interpreter, set program arguments,
+ initiaize threads.
+ */
+void PyInterp_Interp::initPython()
+{
+ if (Py_IsInitialized())
+ return;
+
+ // Python is not initialized
+ Py_SetProgramName(_argv[0]);
+ Py_Initialize(); // Initialize the interpreter
+ PySys_SetArgv(_argc, _argv);
+ PyEval_InitThreads(); // Create (and acquire) the interpreter lock
+ _interp = PyThreadState_Get()->interp;
+ _gtstate = PyEval_SaveThread(); // Release global thread state
+}
+
+/*!
+ \brief Get embedded Python interpreter banner.
+ \return banner string
+ */
+string PyInterp_Interp::getbanner()
+{
+ // Should we take the lock ?
+ // PyEval_RestoreThread(_tstate);
+ string aBanner("Python ");
+ aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
+ aBanner = aBanner + "\ntype help to get general information on environment\n";
+ //PyEval_SaveThread();
+ return aBanner;
+}
+
+/*!
+ \brief Initialize run command.
+
+ This method is used to prepare interpreter for running
+ Python commands.
+
+ \return \c true on success and \c false on error
+*/
+bool PyInterp_Interp::initRun()
+{
+ PySys_SetObject("stderr",_verr);
+ PySys_SetObject("stdout",_vout);
+
+ PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
+ PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
+
+ //PyObject *m = PyImport_GetModuleDict();
+
+ PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
+ PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
+
+ return true;
+}
+
+/*!
+ \brief Compile Python command and evaluate it in the
+ python dictionary context if possible.
+ \internal
+ \param command Python command string
+ \param context Python context (dictionary)
+ \return -1 on fatal error, 1 if command is incomplete and 0
+ if command is executed successfully
+ */
+static int compile_command(const char *command,PyObject *context)
+{
+ 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.
+ //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
+ // PyObjWrapper r(PyEval_EvalCode(v,context,context));
+ //#else
+ PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
+ //#endif
+ if(!r) {
+ // Execution error. We return -1
+ PyErr_Print();
+ return -1;
+ }
+ // The command has been successfully executed. Return 0
+ return 0;
+ }
+}
+
+/*!
+ \brief Run Python command.
+ \param command Python command
+ \return command status
+*/
+int PyInterp_Interp::run(const char *command)
+{
+ beforeRun();
+ return simpleRun(command);
+}
+
+/*!
+ \brief Run Python command (used internally).
+ \param command Python command
+ \param addToHistory if \c true (default), the command is added to the commands history
+ \return command status
+*/
+int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
+{
+ if( addToHistory && strcmp(command,"") != 0 ) {
+ _history.push_back(command);
+ _ith = _history.end();
+ }
+
+ // We come from C++ to enter Python world
+ // We need to acquire the Python global lock
+ //PyLockWrapper aLock(_tstate); // san - lock is centralized now
+
+ // Reset redirected outputs before treatment
+ PySys_SetObject("stderr",_verr);
+ PySys_SetObject("stdout",_vout);
+
+ PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
+ PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
+
+ 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__"));
+
+ return ier;
+}
+
+/*!
+ \brief Get previous command in the commands history.
+ \return previous command
+*/
+const char * PyInterp_Interp::getPrevious()
+{
+ if(_ith != _history.begin()){
+ _ith--;
+ return (*_ith).c_str();
+ }
+ else
+ return BEGIN_HISTORY_PY;
+}
+
+/*!
+ \brief Get next command in the commands history.
+ \return next command
+*/
+const char * PyInterp_Interp::getNext()
+{
+ if(_ith != _history.end()){
+ _ith++;
+ }
+ if (_ith == _history.end())
+ return TOP_HISTORY_PY;
+ else
+ return (*_ith).c_str();
+}
+
+/*!
+ \brief Get standard error output.
+ \return standard error output
+*/
+string PyInterp_Interp::getverr(){
+ //PyLockWrapper aLock(_tstate);
+ PyObjWrapper v(PycStringIO->cgetvalue(_verr));
+ string aRet(PyString_AsString(v));
+ return aRet;
+}
+
+/*!
+ \brief Get standard output.
+ \return standard output
+*/
+string PyInterp_Interp::getvout(){
+ //PyLockWrapper aLock(_tstate);
+ PyObjWrapper v(PycStringIO->cgetvalue(_vout));
+ string aRet(PyString_AsString(v));
+ return aRet;
+}
--- /dev/null
+// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : PyInterp_Interp.h
+// Author : Christian CAREMOLI, Paul RASCLE, EDF
+// Module : SALOME
+
+#ifndef PYINTERP_INTERP_H
+#define PYINTERP_INTERP_H
+
+#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+
+#include <list>
+#include <string>
+
+class PYINTERP_EXPORT PyLockWrapper
+{
+ PyThreadState* myThreadState;
+ PyThreadState* mySaveThreadState;
+ PyGILState_STATE _savestate;
+public:
+ PyLockWrapper(PyThreadState* theThreadState);
+ ~PyLockWrapper();
+};
+
+class PYINTERP_EXPORT PyInterp_Interp
+{
+public:
+ static int _argc;
+ static char* _argv[];
+ static PyObject *builtinmodule;
+ static PyThreadState *_gtstate;
+ static PyInterpreterState *_interp;
+
+ PyInterp_Interp();
+ virtual ~PyInterp_Interp();
+
+ void initialize();
+
+ virtual int run(const char *command);
+
+ PyLockWrapper GetLockWrapper();
+
+ std::string getbanner();
+ std::string getverr();
+ std::string getvout();
+
+ const char * getPrevious();
+ const char * getNext();
+
+protected:
+ PyThreadState * _tstate;
+ PyObject * _vout;
+ PyObject * _verr;
+ PyObject * _g;
+ PyObject * _codeop;
+ std::list<std::string> _history;
+ std::list<std::string>::iterator _ith;
+
+ virtual int beforeRun() { return 0; }
+ int simpleRun(const char* command, const bool addToHistory = true);
+
+ virtual bool initRun();
+ virtual void initPython();
+ virtual bool initState() = 0;
+ virtual bool initContext() = 0;
+};
+
+class PYINTERP_EXPORT PyObjWrapper
+{
+ PyObject* myObject;
+public:
+ PyObjWrapper(PyObject* theObject) : myObject(theObject) {}
+ PyObjWrapper() : myObject(0) {}
+ virtual ~PyObjWrapper() { Py_XDECREF(myObject); }
+
+ operator PyObject*() { return myObject; }
+ PyObject* operator->() { return myObject; }
+ PyObject* get() { return myObject; }
+ bool operator!() { return !myObject; }
+ bool operator==(PyObject* theObject) { return myObject == theObject; }
+ PyObject** operator&() { return &myObject; }
+ PyObjWrapper& operator=(PyObjWrapper* theObjWrapper)
+ {
+ Py_XDECREF(myObject);
+ myObject = theObjWrapper->myObject;
+ return *this;
+ }
+};
+
+#endif // PYINTERP_INTERP_H
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-#ifndef _PYINTERP_WATCHER_H_
-#define _PYINTERP_WATCHER_H_
+// File : PyInterp_Watcher.h
+// Author : Sergey Anikin, OCC
+// Module : SALOME
-#include <PyInterp.h>
+#ifndef PYINTERP_WATCHER_H
+#define PYINTERP_WATCHER_H
-#include <PyInterp_Dispatcher.h>
+#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include <qobject.h>
+#include "PyInterp_Dispatcher.h"
+
+#include <QObject>
// Private class that keeps track of destructions of request listeners
class PYINTERP_EXPORT PyInterp_Watcher : public QObject
void onDestroyed( QObject* o ) { PyInterp_Dispatcher::Get()->objectDestroyed( o ); }
};
-#endif // _PYINTERP_WATCHER_H_
+#endif // PYINTERP_WATCHER_H
+++ /dev/null
-// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
-// File : PyInterp_base.cxx
-// Author : Christian CAREMOLI, Paul RASCLE, EDF
-// Module : SALOME
-// $Header$
-
-
-#include <string>
-#include <vector>
-
-#include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)!
-#include <cStringIO.h>
-
-using namespace std;
-
-PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState):
- myThreadState(theThreadState),
- mySaveThreadState(0)
-{
-#if defined(USE_GILSTATE)
- if (myThreadState->interp == PyInterp_base::_interp) {
- _savestate = PyGILState_Ensure();
- } else {
- PyEval_AcquireThread(myThreadState);
- }
-#else
- PyEval_AcquireThread(myThreadState);
-#endif
-}
-
-PyLockWrapper::~PyLockWrapper()
-{
-#if defined(USE_GILSTATE)
- if (myThreadState->interp == PyInterp_base::_interp) {
- PyGILState_Release(_savestate);
- } else {
- PyEval_ReleaseThread(myThreadState);
- }
-#else
- PyEval_ReleaseThread(myThreadState);
-#endif
-}
-
-class PyReleaseLock{
-public:
- ~PyReleaseLock(){
- PyEval_ReleaseLock();
- }
-};
-
-
-PyLockWrapper PyInterp_base::GetLockWrapper(){
- return _tstate;
-}
-
-
-// main python interpreter (static attributes)
-
-int PyInterp_base::_argc = 1;
-char* PyInterp_base::_argv[] = {""};
-
-PyObject *PyInterp_base::builtinmodule = NULL;
-
-PyThreadState *PyInterp_base::_gtstate = NULL;
-PyInterpreterState *PyInterp_base::_interp = NULL;
-
-
-/*!
- * 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()
-{
-}
-
-
-/*!
- * Must be called by herited classes constructors. initialize() calls virtuals methods
- * initstate & initcontext, not defined here in base class. initstate & initcontext methods
- * must be implemented in herited classes, following the Python interpreter policy
- * (mono or multi interpreter...).
- */
-void PyInterp_base::initialize()
-{
- _history.clear(); // start a new list of user's commands
- _ith = _history.begin();
-
- init_python();
- // Here the global lock is released
-
- initState();
-
- PyLockWrapper aLock= GetLockWrapper();
-
- initContext();
-
- // used to interpret & compile commands
- PyObjWrapper m(PyImport_ImportModule("codeop"));
- if(!m){
- PyErr_Print();
- return;
- }
-
- // Create cStringIO to capture stdout and stderr
- PycString_IMPORT;
- if (PycStringIO) { // CTH11627 : additional check
- _vout = PycStringIO->NewOutput(128);
- _verr = PycStringIO->NewOutput(128);
- }
-
- // All the initRun outputs are redirected to the standard output (console)
- initRun();
-}
-
-void PyInterp_base::init_python()
-{
- _atFirst = false;
- if (Py_IsInitialized())
- return;
-
- // Python is not initialized
- Py_SetProgramName(_argv[0]);
- Py_Initialize(); // Initialize the interpreter
- PySys_SetArgv(_argc, _argv);
- PyEval_InitThreads(); // Create (and acquire) the interpreter lock
- _interp = PyThreadState_Get()->interp;
- _gtstate = PyEval_SaveThread(); // Release global thread state
-}
-
-string PyInterp_base::getbanner()
-{
- // Should we take the lock ?
- // PyEval_RestoreThread(_tstate);
- string aBanner("Python ");
- aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
- aBanner = aBanner + "\ntype help to get general information on environment\n";
- //PyEval_SaveThread();
- return aBanner;
-}
-
-
-int PyInterp_base::initRun()
-{
- PySys_SetObject("stderr",_verr);
- PySys_SetObject("stdout",_vout);
-
- PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
- PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
-
- //PyObject *m = PyImport_GetModuleDict();
-
- PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
- PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
-
- return 0;
-}
-
-
-/*!
- * This function compiles a string (command) and then evaluates it in the dictionnary
- * context if possible.
- * Returns :
- * -1 : fatal error
- * 1 : incomplete text
- * 0 : complete text executed with success
- */
-int compile_command(const char *command,PyObject *context)
-{
- 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.
- //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
- // PyObjWrapper r(PyEval_EvalCode(v,context,context));
- //#else
- PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
- //#endif
- if(!r){
- // Execution error. We return -1
- PyErr_Print();
- return -1;
- }
- // The command has been successfully executed. Return 0
- return 0;
- }
-}
-
-
-int PyInterp_base::run(const char *command)
-{
- if(_atFirst){
- int ret = 0;
- ret = simpleRun("from Help import *");
- if (ret) {
- _atFirst = false;
- return ret;
- }
- ret = simpleRun("import salome");
- if (ret) {
- _atFirst = false;
- return ret;
- }
- ret = simpleRun("salome.salome_init(0,1)");
- if (ret) {
- _atFirst = false;
- return ret;
- }
- _atFirst = false;
- }
- return simpleRun(command);
-}
-
-
-int PyInterp_base::simpleRun(const char *command)
-{
- if( !_atFirst && strcmp(command,"") != 0 ) {
- _history.push_back(command);
- _ith = _history.end();
- }
-
- // We come from C++ to enter Python world
- // We need to acquire the Python global lock
- //PyLockWrapper aLock(_tstate); // san - lock is centralized now
-
- // Reset redirected outputs before treatment
- PySys_SetObject("stderr",_verr);
- PySys_SetObject("stdout",_vout);
-
- PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
- PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
-
- 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__"));
-
- return ier;
-}
-
-
-const char * PyInterp_base::getPrevious()
-{
- if(_ith != _history.begin()){
- _ith--;
- return (*_ith).c_str();
- }
- else
- return BEGIN_HISTORY_PY;
-}
-
-
-const char * PyInterp_base::getNext()
-{
- 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;
-}
+++ /dev/null
-// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
-// File : PyInterp_base.h
-// Author : Christian CAREMOLI, Paul RASCLE, EDF
-// Module : SALOME
-
-#ifndef _PYINTERP_BASE_H_
-#define _PYINTERP_BASE_H_
-
-#include "PyInterp.h"
-
-#include <list>
-#include <string>
-#include <iostream>
-
-// include order important!
-// pthread then python then qt
-//#include <pthread.h> // must be before Python.h !
-
-#include <Python.h> // must be before qt includes ...
-#include <compile.h> // Python include needed for versions before 2.4. Included in Python.h now.
-#include <eval.h> // Python include needed for versions before 2.4. Included in Python.h now.
-
-//#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
-//extern "C" PyObject * PyEval_EvalCode(PyObject *co, PyObject *g, PyObject *l);
-//#endif
-
-/* For 2.3, use the PyGILState_ calls */
-#if (PY_VERSION_HEX >= 0x02030000)
-#define USE_GILSTATE
-#endif
-
-#define TOP_HISTORY_PY "--- top of history ---"
-#define BEGIN_HISTORY_PY "--- begin of history ---"
-
-class PYINTERP_EXPORT PyLockWrapper
-{
- PyThreadState* myThreadState;
- PyThreadState* mySaveThreadState;
-#if defined(USE_GILSTATE)
- PyGILState_STATE _savestate ;
-#endif
- public:
- PyLockWrapper(PyThreadState* theThreadState);
- ~PyLockWrapper();
-};
-
-class PYINTERP_EXPORT PyInterp_base{
- public:
- static int _argc;
- static char* _argv[];
- static PyObject *builtinmodule;
- static PyThreadState *_gtstate;
- static PyInterpreterState *_interp;
-
- PyInterp_base();
- ~PyInterp_base();
-
- virtual void initialize();
- virtual void init_python();
- // init_python() made virtual to:
- // 1. Remove dependency on KERNEL in light SALOME configuration
- // 2. Allow redefinition of this method in SalomeApp_PyInterp class (it should be empty there and rely on KERNEL_PYTHON)
-
- virtual int run(const char *command);
-
- PyLockWrapper GetLockWrapper();
-
- std::string getbanner();
- std::string getverr();
- std::string getvout();
-
- const char * getPrevious();
- const char * getNext();
-
- protected:
- PyThreadState * _tstate;
- PyObject * _vout;
- PyObject * _verr;
- PyObject * _g;
- PyObject * _codeop;
- std::list<std::string> _history;
- std::list<std::string>::iterator _ith;
- bool _atFirst;
-
- int simpleRun(const char* command);
- int initRun();
-
- virtual bool initState() = 0;
- virtual bool initContext() = 0;
-};
-
-
-class PYINTERP_EXPORT PyObjWrapper{
- PyObject* myObject;
-public:
- PyObjWrapper(PyObject* theObject): myObject(theObject) {}
- PyObjWrapper(): myObject(0) {}
- operator PyObject*(){
- return myObject;
- }
- PyObject* operator->(){
- return myObject;
- }
- PyObject* get(){
- return myObject;
- }
- bool operator!(){
- return !myObject;
- }
- bool operator==(PyObject* theObject){
- return myObject == theObject;
- }
- PyObject** operator&(){
- return &myObject;
- }
- PyObjWrapper& operator=(PyObjWrapper* theObjWrapper){
- Py_XDECREF(myObject);
- myObject = theObjWrapper->myObject;
- return *this;
- }
- virtual ~PyObjWrapper(){
- Py_XDECREF(myObject);
- }
-};
-
-#endif