Salome HOME
NRI : Add KERNEL_ROOT_DIR in addition to SALOME_[ROOT, SITE]_DIR.
[modules/kernel.git] / src / SALOMEGUI / PyInterp_base.cxx
1 using namespace std;
2 //=============================================================================
3 // File      : PyInterp_base.cxx
4 // Created   : ven fév  7 10:01:36 CET 2003
5 // Author    : Christian CAREMOLI, Paul RASCLE, EDF
6 // Project   : SALOME
7 // Copyright : EDF 2003
8 // $Header$
9 //=============================================================================
10
11 #include "PyInterp_base.h"
12 #include "utilities.h"
13 #include <string>
14 #include <vector>
15 #include <cStringIO.h>
16
17 using namespace std;
18
19 extern "C" PyObject * PyEval_EvalCode(PyObject *co, PyObject *g, PyObject *l);
20
21 static PyThreadState *savedThreadState = NULL;
22
23 /*!
24  * We have our own routines which are identical to the SIP routines
25  * to not depend from SIP software evolutions
26  */
27
28 extern "C" void salomeAcquireLock()
29 {
30   MESSAGE("salomeAcquireLock");
31   PyEval_RestoreThread(savedThreadState);
32   savedThreadState = NULL;
33 }
34
35 extern "C" void salomeReleaseLock()
36 {
37   MESSAGE("salomeReleaseLock");
38   savedThreadState = PyEval_SaveThread();
39 }
40
41 extern "C" int salomeCondAcquireLock()
42 {
43   MESSAGE("salomeCondAcquireLock");
44   if(savedThreadState != NULL)
45     {
46       /*
47        * If savedThreadState is not NULL, Python global lock is not already acquired
48        * We acquire it
49        * and return 1 to the caller
50        */
51       salomeAcquireLock();
52       //MESSAGE("We got it (the lock)");
53       return 1;
54     }
55   /*
56    * If savedThreadState is NULL, Python global lock is already acquired
57    * We don't acquire or release it
58    * We return 0 to the caller
59    * CAUTION : it's only true when there is no event programming running (Tkinter, PyQt)
60    */
61   return 0;
62 }
63
64 extern "C" void salomeCondReleaseLock(int rellock)
65 {
66   MESSAGE("salomeCondReleaseLock");
67   if(rellock )
68     salomeReleaseLock();
69 }
70
71 // main python interpreter
72
73 PyThreadState *PyInterp_base::_gtstate=0; // force 0 before execution
74 int PyInterp_base::_argc=1;
75 char* PyInterp_base::_argv[] = {""};
76
77 PyObject *PyInterp_base::builtinmodule=NULL;
78 PyObject *PyInterp_base::salome_shared_modules_module=NULL;
79
80 void init_python()
81 {
82   SCRUTE(PyInterp_base::_gtstate);
83   if (PyInterp_base::_gtstate) return;
84   Py_Initialize();               // Initialize the interpreter
85   PyEval_InitThreads();          // Create (and acquire) the interpreter lock
86   PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv);      // initialize sys.argv
87   PyInterp_base::_gtstate = PyThreadState_Get();
88   SCRUTE(PyInterp_base::_gtstate);
89
90   //   /*
91   //    * Import __builtin__ module and store it to use it with all sub-interpreters
92   //    * This hack could be used with event programming (PyQt) to avoid errors 
93   //    * encountered with incoherent builtins
94   //    */
95
96   //   PyInterp_base::builtinmodule =PyImport_ImportModule("__builtin__");
97   //   SCRUTE(PyInterp_base::builtinmodule->ob_refcnt);
98
99   /*
100    * Import salome_shared_modules module and store it to use it with all sub-interpreters
101    */
102
103   PyInterp_base::salome_shared_modules_module =PyImport_ImportModule("salome_shared_modules");
104   SCRUTE(PyInterp_base::salome_shared_modules_module->ob_refcnt);
105
106   salomeReleaseLock();
107 }
108
109 /*!
110  * This function compiles a string (command) and then evaluates it in the dictionnary
111  * context if possible.
112  * Returns :
113  * -1 : fatal error 
114  *  1 : incomplete text
115  *  0 : complete text executed with success
116  */
117
118 int compile_command(const char *command,PyObject *context)
119 {
120   SCRUTE(command);
121   PyObject *m,*v,*r;
122
123   m=PyImport_AddModule("codeop");
124   if(m == NULL)
125     {
126       /*
127        * Fatal error. No way to go on.
128        */
129       PyErr_Print();
130       return -1;
131     }
132   v= PyObject_CallMethod(m,"compile_command","s",command);
133   if (v == NULL)
134     {
135       /*
136        * Error encountered. It could be SyntaxError
137        */
138       PyErr_Print();
139       return -1;
140     }
141   else if (v == Py_None)
142     {
143       /*
144        *  Incomplete text we return 1 : we need a complete text to execute
145        */
146       return 1;
147     }
148   else
149     {
150       /*
151        * Complete and correct text. We evaluate it.
152        */
153       r  = PyEval_EvalCode(v,context,context);
154       Py_DECREF(v);
155       if (r==NULL)
156         {
157           /*
158            * Execution error. We return -1
159            */
160           PyErr_Print();
161           return -1;
162         }
163       Py_DECREF(r);
164       /*
165        * The command has been successfully executed. Return 0
166        */
167       return 0;
168     }
169 }
170
171 /*!
172  * basic constructor here : herited classes constructors must call initalize() method
173  * defined here.
174  */
175
176 PyInterp_base::PyInterp_base():_tstate(0),_vout(0),_verr(0),_g(0),_atFirst(true)
177 {
178   MESSAGE("PyInterp_base::PyInterp_base()");
179 }
180
181 PyInterp_base::~PyInterp_base()
182 {
183   MESSAGE("PyInterp_base::~PyInterp_base()");
184   salomeAcquireLock();
185   PyThreadState_Swap(_tstate);
186   Py_EndInterpreter(_tstate);
187   salomeReleaseLock();
188 }
189
190 /*!
191  * Must be called by herited classes constructors. initialize() calls virtuals methods
192  * initstate & initcontext, not defined here in base class. initstate & initcontext methods
193  * must be implemented in herited classes, following the Python interpreter policy
194  * (mono or multi interpreter...).
195  */
196 void PyInterp_base::initialize()
197 {
198   MESSAGE("PyInterp_base::initialize()");
199   PyObject *m,*v,*c;
200
201   _history.clear();       // start a new list of user's commands 
202   _ith = _history.begin();
203
204   init_python();
205
206   initState();
207
208   initContext();
209
210   m=PyImport_ImportModule("codeop"); // used to interpret & compile commands
211   if(m == NULL)
212     {
213       MESSAGE("Problem...");
214       ASSERT(0);
215       PyErr_Print();
216       salomeReleaseLock(); 
217       return;
218     }   
219   Py_DECREF(m);   
220   
221   /*
222    *  Create cStringIO to capture stdout and stderr
223    */
224   //PycString_IMPORT;
225   PycStringIO=(PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
226   _vout=PycStringIO->NewOutput(128);
227   _verr=PycStringIO->NewOutput(128);
228   
229   // All the initRun outputs are redirected to the standard output (console)
230   this->initRun();
231
232   // We go out of Python world to enter the C++ world. Release the Python global lock 
233   salomeReleaseLock();
234   SCRUTE(_tstate);
235   SCRUTE(this);
236 }
237
238 string PyInterp_base::getbanner()
239 {
240   MESSAGE("PyInterp_base::getbanner()");
241   string banner = "Python ";
242   banner = banner + Py_GetVersion() + " on " + Py_GetPlatform() ;
243   banner = banner + "\ntype help to get general information on environment\n";
244   return banner.c_str();
245 }
246
247 int PyInterp_base::initRun()
248 {
249   MESSAGE("PyInterp_base::initRun()");
250   PySys_SetObject("stderr",_verr);
251   PySys_SetObject("stdout",_vout);
252
253   PyObject *v = PyObject_CallMethod(_verr,"reset","");
254   Py_XDECREF(v);
255   v = PyObject_CallMethod(_vout,"reset","");
256   Py_XDECREF(v);
257
258
259   PyObject *m;
260   m = PyImport_GetModuleDict();
261   
262   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
263   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
264
265   MESSAGE(this->getvout());
266   MESSAGE(this->getverr());
267     
268   return 0;
269 }
270
271 void PyInterp_base::enter()
272 {
273   MESSAGE("PyInterp_base::enter()");
274   salomeAcquireLock();
275   PyThreadState_Swap(_tstate);
276 }
277
278 void PyInterp_base::quit()
279 {
280   MESSAGE("PyInterp_base::quit()");
281   salomeReleaseLock();
282 }
283
284 void PyInterp_base::basicRun(const char *command)
285 {
286   SCRUTE(command);
287   PyObject *code,*r;
288   enter();
289   code=Py_CompileString((char *)command,"PyInterp_base",Py_file_input);
290   if (code == NULL)
291     {
292       /*
293        * Caught an error : SyntaxError
294        * Print it and quit
295        */
296       PyErr_Print();
297       quit();
298       return;
299     }
300   r = PyEval_EvalCode(code,_g,_g);
301   Py_DECREF(code);
302   if (r==NULL)
303     {
304       /*
305        * Caught an error during execution
306        * Print it and quit
307        */
308       PyErr_Print();
309       quit();
310       return;
311     }
312   Py_DECREF(r);
313   quit();
314 }
315
316 int PyInterp_base::run(const char *command)
317 {
318   SCRUTE(command);
319   int ret = 0;
320   if (_atFirst)
321     {
322       _atFirst = false;
323       ret = this->simpleRun("from Help import *");
324       MESSAGE(this->getvout())
325         MESSAGE(this->getverr())
326         if (ret != 0) return ret;
327       ret = this->simpleRun("import salome");
328       MESSAGE(this->getvout());
329       MESSAGE(this->getverr())
330         if (ret != 0) return ret;
331     }
332   ret = this->simpleRun(command);
333   return ret;
334 }
335
336 int PyInterp_base::simpleRun(const char *command)
337 {
338   SCRUTE(command);
339   PyObject *v,*m,*r,*g;
340   char *output;
341   int ier=0;
342   string s_com = command;
343
344   if (s_com.size() > 0)
345     {
346       _history.push_back(s_com);
347       _ith = _history.end();
348       SCRUTE(_history.back());
349     }
350
351   //   SCRUTE(this);
352   //   SCRUTE(_tstate);
353   // We come from C++ to enter Python world
354   // We need to acquire the Python global lock
355   salomeAcquireLock();
356   // Restore the sub interpreter thread state : this._tstate
357   PyThreadState_Swap(_tstate);
358
359   /*
360     Reset redirected outputs before treatment
361   */
362   PySys_SetObject("stderr",_verr);
363   PySys_SetObject("stdout",_vout);
364
365   v = PyObject_CallMethod(_verr,"reset","");
366   Py_XDECREF(v);
367   v = PyObject_CallMethod(_vout,"reset","");
368   Py_XDECREF(v);
369   
370   ier=compile_command(command,_g);
371
372   // Outputs are redirected on standards outputs (console)
373   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
374   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
375
376   // We go back to the C++ world. Release the lock.
377   salomeReleaseLock();
378   return ier;
379 }
380
381 static string vout_buffer;
382 static string verr_buffer;
383
384 char * PyInterp_base::getverr()
385
386   MESSAGE("PyInterp_base::getverr"); 
387   PyObject *v;
388   v=PycStringIO->cgetvalue(_verr);
389   verr_buffer=PyString_AsString(v);
390   Py_DECREF(v);
391   return (char *)verr_buffer.c_str();
392 }
393
394 char * PyInterp_base::getvout()
395 {  
396   MESSAGE("PyInterp_base::getvout"); 
397   PyObject *v;
398   v=PycStringIO->cgetvalue(_vout);
399   vout_buffer=PyString_AsString(v);
400   Py_DECREF(v);
401   return (char *)vout_buffer.c_str();
402 }
403  
404 const char * PyInterp_base::getPrevious()
405 {
406   MESSAGE("PyInterp_base::getPrevious"); 
407   if (_ith != _history.begin())
408     {
409       _ith--;
410       return (*_ith).c_str();
411     }
412   else
413     return BEGIN_HISTORY_PY;
414 }
415
416 const char * PyInterp_base::getNext()
417 {
418   MESSAGE("PyInterp_base::getNext"); 
419   if (_ith != _history.end())
420     {
421       _ith++;
422     }
423   if (_ith == _history.end())
424     return TOP_HISTORY_PY;
425   else
426     return (*_ith).c_str();
427 }