]> SALOME platform Git repositories - modules/yacs.git/blob - src/SALOMEGUI/PyInterp_base.cxx
Salome HOME
83ea5e0409656dc03b06ec4d864332f6f0becfb3
[modules/yacs.git] / src / SALOMEGUI / PyInterp_base.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : PyInterp_base.cxx
8 //  Author : Christian CAREMOLI, Paul RASCLE, EDF
9 //  Module : SALOME
10 //  $Header$
11
12
13
14 #include <string>
15 #include <vector>
16
17 #include <Python.h>
18 #include <cStringIO.h>
19
20 #include <qmutex.h>
21
22 #include "PyInterp_base.h"
23 #include "utilities.h"
24
25
26 using namespace std;
27
28
29 #ifdef _DEBUG_
30 static int MYDEBUG = 0;
31 static int MYPYDEBUG = 0;
32 #else
33 static int MYDEBUG = 0;
34 static int MYPYDEBUG = 0;
35 #endif
36
37
38 static QMutex myMutex(false);
39
40
41 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
42   myThreadState(theThreadState),
43   mySaveThreadState(PyInterp_base::_gtstate)
44 {
45   PyEval_AcquireLock();
46   mySaveThreadState = PyThreadState_Swap(myThreadState);
47 }
48
49
50 PyLockWrapper::~PyLockWrapper(){
51   PyThreadState_Swap(mySaveThreadState);
52   PyEval_ReleaseLock();
53 }
54
55
56 ThreadLock::ThreadLock(QMutex* theMutex, const char* theComment):
57   myMutex(theMutex),
58   myComment(theComment)
59 {
60   if(MYDEBUG && myComment != "") MESSAGE(" ThreadLock "<<this<<"::"<<myMutex<<" - "<<myComment<<" - "<<myMutex->locked());
61   myMutex->lock();
62 }
63
64
65 ThreadLock::~ThreadLock(){
66   if(MYDEBUG && myComment != "") MESSAGE("~ThreadLock "<<this<<"::"<<myMutex<<" - "<<myComment);
67   myMutex->unlock();
68 }
69
70
71 bool IsPyLocked(){
72   return myMutex.locked();
73 }
74
75
76 ThreadLock GetPyThreadLock(const char* theComment){
77   return ThreadLock(&myMutex,theComment);
78 }
79
80
81 class PyReleaseLock{
82 public:
83   ~PyReleaseLock(){
84     if(MYPYDEBUG) MESSAGE("~PyReleaseLock()");
85     PyEval_ReleaseLock();
86   }
87 };
88
89
90 PyLockWrapper PyInterp_base::GetLockWrapper(){
91   return _tstate;
92 }
93
94
95 // main python interpreter
96
97 PyThreadState *PyInterp_base::_gtstate = 0; // force 0 before execution
98 int PyInterp_base::_argc = 1;
99 char* PyInterp_base::_argv[] = {""};
100
101 PyObject *PyInterp_base::builtinmodule = NULL;
102 PyObject *PyInterp_base::salome_shared_modules_module = NULL;
103
104
105 /*!
106  * basic constructor here : herited classes constructors must call initalize() method
107  * defined here.
108  */
109 PyInterp_base::PyInterp_base(): _tstate(0), _vout(0), _verr(0), _g(0), _atFirst(true)
110 {
111   if(MYPYDEBUG) MESSAGE("PyInterp_base::PyInterp_base() - this = "<<this);
112 }
113
114 PyInterp_base::~PyInterp_base()
115 {
116   if(MYPYDEBUG) MESSAGE("PyInterp_base::~PyInterp_base() - this = "<<this);
117   PyLockWrapper aLock(_tstate);
118   //Py_EndInterpreter(_tstate);
119 }
120
121
122 /*!
123  * Must be called by herited classes constructors. initialize() calls virtuals methods
124  * initstate & initcontext, not defined here in base class. initstate & initcontext methods
125  * must be implemented in herited classes, following the Python interpreter policy
126  * (mono or multi interpreter...).
127  */
128 void PyInterp_base::initialize()
129 {
130   _history.clear();       // start a new list of user's commands 
131   _ith = _history.begin();
132
133   if(!_gtstate){
134     PyReleaseLock aReleaseLock;
135     Py_Initialize(); // Initialize the interpreter
136     PyEval_InitThreads(); // Initialize and acquire the global interpreter lock
137     PySys_SetArgv(_argc,_argv); // initialize sys.argv
138     _gtstate = PyThreadState_Get();
139     
140     /*
141      * salome_shared_modules should be imported only once
142      */
143     salome_shared_modules_module = PyImport_ImportModule("salome_shared_modules");
144     if(!salome_shared_modules_module)
145       {
146         INFOS("PyInterp_base::initialize() - salome_shared_modules_module == NULL");
147         PyErr_Print();
148         PyErr_Clear();
149       }
150   }
151   // Here the global lock is released
152   if(MYPYDEBUG) MESSAGE("PyInterp_base::initialize() - this = "<<this<<"; _gtstate = "<<_gtstate);
153
154   // The lock will be acquired in initState. Make provision to release it on exit
155   PyReleaseLock aReleaseLock;
156
157   initState();
158   initContext();
159
160   // used to interpret & compile commands
161   PyObjWrapper m(PyImport_ImportModule("codeop"));
162   if(!m){
163     INFOS("PyInterp_base::initialize() - PyImport_ImportModule('codeop') failed");
164     PyErr_Print();
165     ASSERT(0);
166     return;
167   }   
168   
169   // Create cStringIO to capture stdout and stderr
170   //PycString_IMPORT;
171   PycStringIO = (PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
172   _vout = PycStringIO->NewOutput(128);
173   _verr = PycStringIO->NewOutput(128);
174   
175   // All the initRun outputs are redirected to the standard output (console)
176   initRun();
177 }
178
179
180 string PyInterp_base::getbanner()
181 {
182   string aBanner("Python ");
183   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
184   aBanner = aBanner + "\ntype help to get general information on environment\n";
185   return aBanner;
186 }
187
188
189 int PyInterp_base::initRun()
190 {
191   PySys_SetObject("stderr",_verr);
192   PySys_SetObject("stdout",_vout);
193
194   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
195   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
196
197   PyObject *m = PyImport_GetModuleDict();
198   
199   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
200   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
201
202   if(MYPYDEBUG) MESSAGE("PyInterp_base::initRun() - this = "<<this<<"; _verr = "<<_verr<<"; _vout = "<<_vout);
203   return 0;
204 }
205
206
207 /*!
208  * This function compiles a string (command) and then evaluates it in the dictionnary
209  * context if possible.
210  * Returns :
211  * -1 : fatal error 
212  *  1 : incomplete text
213  *  0 : complete text executed with success
214  */
215 int compile_command(const char *command,PyObject *context)
216 {
217   PyObject *m = PyImport_AddModule("codeop");
218   if(!m){ // Fatal error. No way to go on.
219     PyErr_Print();
220     return -1;
221   }
222   PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
223   if(!v){
224     // Error encountered. It should be SyntaxError,
225     //so we don't write out traceback
226     PyObjWrapper exception, value, tb;
227     PyErr_Fetch(&exception, &value, &tb);
228     PyErr_NormalizeException(&exception, &value, &tb);
229     PyErr_Display(exception, value, NULL);
230     return -1;
231   }else if (v == Py_None){
232     // Incomplete text we return 1 : we need a complete text to execute
233     return 1;
234   }else{
235     // Complete and correct text. We evaluate it.
236     PyObjWrapper r(PyEval_EvalCode(v,context,context));
237     if(!r){
238       // Execution error. We return -1
239       PyErr_Print();
240       return -1;
241     }
242     // The command has been successfully executed. Return 0
243     return 0;
244   }
245 }
246
247
248 int PyInterp_base::run(const char *command)
249 {
250   if(_atFirst){
251     int ret = 0;
252     _atFirst = false;
253     ret = simpleRun("from Help import *");
254     if (ret) return ret;
255     ret = simpleRun("import salome");
256     if (ret) return ret;
257   }
258   return simpleRun(command);
259 }
260
261
262 int PyInterp_base::simpleRun(const char *command)
263 {
264   if(strcmp(command,"") != 0){
265     _history.push_back(command);
266     _ith = _history.end();
267   }
268
269   // We come from C++ to enter Python world
270   // We need to acquire the Python global lock
271   PyLockWrapper aLock(_tstate);
272
273   // Reset redirected outputs before treatment
274   PySys_SetObject("stderr",_verr);
275   PySys_SetObject("stdout",_vout);
276     
277   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
278   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
279   
280   int ier = compile_command(command,_g);
281
282   // Outputs are redirected on standards outputs (console)
283   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
284   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
285   return ier;
286 }
287
288
289 const char * PyInterp_base::getPrevious()
290 {
291   if(_ith != _history.begin()){
292     _ith--;
293     return (*_ith).c_str();
294   }
295   else
296     return BEGIN_HISTORY_PY;
297 }
298
299
300 const char * PyInterp_base::getNext()
301 {
302   if(_ith != _history.end()){
303     _ith++;
304   }
305   if (_ith == _history.end())
306     return TOP_HISTORY_PY;
307   else
308     return (*_ith).c_str();
309 }
310
311
312 string PyInterp_base::getverr(){ 
313   PyLockWrapper aLock(_tstate);
314   PyObjWrapper v(PycStringIO->cgetvalue(_verr));
315   string aRet(PyString_AsString(v));
316   return aRet;
317 }
318
319
320 string PyInterp_base::getvout(){  
321   PyLockWrapper aLock(_tstate);
322   PyObjWrapper v(PycStringIO->cgetvalue(_vout));
323   string aRet(PyString_AsString(v));
324   return aRet;
325 }
326