1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : PyInterp_Interp.cxx
24 // Author : Christian CAREMOLI, Paul RASCLE, EDF
27 #include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
30 #include <cStringIO.h>
31 #include <structmember.h>
38 #define TOP_HISTORY_PY "--- top of history ---"
39 #define BEGIN_HISTORY_PY "--- begin of history ---"
41 // a map to store python thread states that have been created for a given system thread (key=thread id,value=thread state)
42 std::map<long,PyThreadState*> currentThreadMap;
46 \brief Python GIL wrapper.
50 \brief Constructor. Automatically acquires GIL.
51 \param theThreadState python thread state
53 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState):
54 myThreadState(theThreadState),
57 if (myThreadState->interp == PyInterp_Interp::_interp)
58 _savestate = PyGILState_Ensure();
60 PyEval_AcquireThread(myThreadState);
64 \brief Destructor. Automatically releases GIL.
66 PyLockWrapper::~PyLockWrapper()
68 if (myThreadState->interp == PyInterp_Interp::_interp)
69 PyGILState_Release(_savestate);
71 PyEval_ReleaseThread(myThreadState);
75 \brief Get Python GIL wrapper.
76 \return GIL lock wrapper (GIL is automatically acquired here)
78 PyLockWrapper PyInterp_Interp::GetLockWrapper()
80 if (_tstate->interp == PyInterp_Interp::_interp)
83 // If we are here, we have a secondary python interpreter. Try to get a thread state synchronized with the system thread
84 long currentThreadid=PyThread_get_thread_ident(); // the system thread id
85 PyThreadState* theThreadState;
86 if(currentThreadMap.count(currentThreadid) != 0)
88 //a thread state exists for this thread id
89 PyThreadState* oldThreadState=currentThreadMap[currentThreadid];
90 if(_tstate->interp ==oldThreadState->interp)
92 //The old thread state has the same python interpreter as this one : reuse the threadstate
93 theThreadState=oldThreadState;
97 //The old thread state has not the same python interpreter as this one : delete the old threadstate and create a new one
99 PyThreadState_Clear(oldThreadState);
100 PyThreadState_Delete(oldThreadState);
101 PyEval_ReleaseLock();
102 theThreadState=PyThreadState_New(_tstate->interp);
103 currentThreadMap[currentThreadid]=theThreadState;
108 // no old thread state for this thread id : create a new one
109 theThreadState=PyThreadState_New(_tstate->interp);
110 currentThreadMap[currentThreadid]=theThreadState;
112 return theThreadState;
116 The following functions are used to hook the Python
121 PyStdOut_dealloc(PyStdOut *self)
127 PyStdOut_write(PyStdOut *self, PyObject *args)
131 if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
133 if(self->_cb==NULL) {
140 self->_cb(self->_data,c);
147 PyStdOut_flush(PyStdOut *self)
153 static PyMethodDef PyStdOut_methods[] = {
154 {"write", (PyCFunction)PyStdOut_write, METH_VARARGS, PyDoc_STR("write(string) -> None")},
155 {"flush", (PyCFunction)PyStdOut_flush, METH_NOARGS, PyDoc_STR("flush() -> None")},
156 {NULL, NULL} /* sentinel */
159 static PyMemberDef PyStdOut_memberlist[] = {
160 {(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
161 (char*)"flag indicating that a space needs to be printed; used by print"},
162 {NULL} /* Sentinel */
165 static PyTypeObject PyStdOut_Type = {
166 /* The ob_type field must be initialized in the module init function
167 * to be portable to Windows without using C++. */
168 PyObject_HEAD_INIT(NULL)
171 sizeof(PyStdOut), /*tp_basicsize*/
174 (destructor)PyStdOut_dealloc, /*tp_dealloc*/
181 0, /*tp_as_sequence*/
186 PyObject_GenericGetAttr, /*tp_getattro*/
187 /* softspace is writable: we must supply tp_setattro */
188 PyObject_GenericSetAttr, /* tp_setattro */
190 Py_TPFLAGS_DEFAULT, /*tp_flags*/
194 0, /*tp_richcompare*/
195 0, /*tp_weaklistoffset*/
198 PyStdOut_methods, /*tp_methods*/
199 PyStdOut_memberlist, /*tp_members*/
213 #define PyStdOut_Check(v) ((v)->ob_type == &PyStdOut_Type)
215 static PyStdOut* newPyStdOut( bool iscerr )
218 self = PyObject_New(PyStdOut, &PyStdOut_Type);
223 self->_iscerr = iscerr;
228 \class PyInterp_Interp
229 \brief Generic embedded Python interpreter.
232 int PyInterp_Interp::_argc = 1;
233 char* PyInterp_Interp::_argv[] = {(char*)""};
234 PyObject* PyInterp_Interp::builtinmodule = NULL;
235 PyThreadState* PyInterp_Interp::_gtstate = NULL;
236 PyInterpreterState* PyInterp_Interp::_interp = NULL;
239 \brief Basic constructor.
241 After construction the interpreter instance successor classes
242 must call virtual method initalize().
244 PyInterp_Interp::PyInterp_Interp():
245 _tstate(0), _vout(0), _verr(0), _g(0)
252 PyInterp_Interp::~PyInterp_Interp()
257 \brief Initialize embedded interpreter.
259 This method shoud be called after construction of the interpreter.
260 The method initialize() calls virtuals methods
261 - initPython() to initialize global Python interpreter
262 - initState() to initialize embedded interpreter state
263 - initContext() to initialize interpreter internal context
264 - initRun() to prepare interpreter for running commands
265 which should be implemented in the successor classes, according to the
266 embedded Python interpreter policy (mono or multi interpreter, etc).
268 void PyInterp_Interp::initialize()
270 _history.clear(); // start a new list of user's commands
271 _ith = _history.begin();
274 // Here the global lock is released
278 PyEval_AcquireThread(_tstate);
282 // used to interpret & compile commands
283 PyObjWrapper m(PyImport_ImportModule("codeop"));
286 PyEval_ReleaseThread(_tstate);
290 // Create python objects to capture stdout and stderr
291 _vout=(PyObject*)newPyStdOut( false ); // stdout
292 _verr=(PyObject*)newPyStdOut( true ); // stderr
294 // All the initRun outputs are redirected to the standard output (console)
296 PyEval_ReleaseThread(_tstate);
300 \brief Initialize Python interpreter.
302 In case if Python is not initialized, it sets program name, initializes the interpreter, sets program arguments,
304 Otherwise, it just obtains the global interpreter and thread states. This is important for light SALOME configuration,
305 as in full SALOME this is done at SalomeApp level.
306 \sa SalomeApp_PyInterp class
308 void PyInterp_Interp::initPython()
310 if (!Py_IsInitialized()){
311 // Python is not initialized
312 Py_SetProgramName(_argv[0]);
313 Py_Initialize(); // Initialize the interpreter
314 PySys_SetArgv(_argc, _argv);
315 PyEval_InitThreads(); // Create (and acquire) the interpreter lock
318 if ( _interp == NULL )
319 _interp = PyThreadState_Get()->interp;
320 if (PyType_Ready(&PyStdOut_Type) < 0) {
323 if ( _gtstate == NULL )
324 _gtstate = PyEval_SaveThread(); // Release global thread state
328 \brief Get embedded Python interpreter banner.
329 \return banner string
331 std::string PyInterp_Interp::getbanner()
333 // Should we take the lock ?
334 // PyEval_RestoreThread(_tstate);
335 std::string aBanner("Python ");
336 aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
337 aBanner = aBanner + "\ntype help to get general information on environment\n";
338 //PyEval_SaveThread();
343 \brief Initialize run command.
345 This method is used to prepare interpreter for running
348 \return \c true on success and \c false on error
350 bool PyInterp_Interp::initRun()
353 // probably all below code isn't required
356 PySys_SetObject("stderr",_verr);
357 PySys_SetObject("stdout",_vout);
359 //PyObject *m = PyImport_GetModuleDict();
361 PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
362 PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
368 \brief Compile Python command and evaluate it in the
369 python dictionary context if possible.
371 \param command Python command string
372 \param context Python context (dictionary)
373 \return -1 on fatal error, 1 if command is incomplete and 0
374 if command is executed successfully
376 static int compile_command(const char *command,PyObject *context)
378 PyObject *m = PyImport_AddModule("codeop");
379 if(!m) { // Fatal error. No way to go on.
383 PyObjWrapper v(PyObject_CallMethod(m,(char*)"compile_command",(char*)"s",command));
385 // Error encountered. It should be SyntaxError,
386 //so we don't write out traceback
387 PyObjWrapper exception, value, tb;
388 PyErr_Fetch(&exception, &value, &tb);
389 PyErr_NormalizeException(&exception, &value, &tb);
390 PyErr_Display(exception, value, NULL);
393 else if (v == Py_None) {
394 // Incomplete text we return 1 : we need a complete text to execute
398 // Complete and correct text. We evaluate it.
399 //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
400 // PyObjWrapper r(PyEval_EvalCode(v,context,context));
402 PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
405 // Execution error. We return -1
409 // The command has been successfully executed. Return 0
415 \brief Run Python command.
416 \param command Python command
417 \return command status
419 int PyInterp_Interp::run(const char *command)
422 return simpleRun(command);
426 \brief Run Python command (used internally).
427 \param command Python command
428 \param addToHistory if \c true (default), the command is added to the commands history
429 \return command status
431 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
433 if( addToHistory && strcmp(command,"") != 0 ) {
434 _history.push_back(command);
435 _ith = _history.end();
438 // We come from C++ to enter Python world
439 // We need to acquire the Python global lock
440 //PyLockWrapper aLock(_tstate); // san - lock is centralized now
442 // Reset redirected outputs before treatment
443 PySys_SetObject((char*)"stderr",_verr);
444 PySys_SetObject((char*)"stdout",_vout);
446 int ier = compile_command(command,_g);
448 // Outputs are redirected on standards outputs (console)
449 PySys_SetObject((char*)"stdout",PySys_GetObject((char*)"__stdout__"));
450 PySys_SetObject((char*)"stderr",PySys_GetObject((char*)"__stderr__"));
456 \brief Get previous command in the commands history.
457 \return previous command
459 const char * PyInterp_Interp::getPrevious()
461 if(_ith != _history.begin()){
463 return (*_ith).c_str();
466 return BEGIN_HISTORY_PY;
470 \brief Get next command in the commands history.
473 const char * PyInterp_Interp::getNext()
475 if(_ith != _history.end()){
478 if (_ith == _history.end())
479 return TOP_HISTORY_PY;
481 return (*_ith).c_str();
485 \brief Set Python standard output device hook.
486 \param cb callback function
487 \param data callback function parameters
489 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
491 ((PyStdOut*)_vout)->_cb=cb;
492 ((PyStdOut*)_vout)->_data=data;
496 \brief Set Python standard error device hook.
497 \param cb callback function
498 \param data callback function parameters
500 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
502 ((PyStdOut*)_verr)->_cb=cb;
503 ((PyStdOut*)_verr)->_data=data;