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