]> SALOME platform Git repositories - modules/yacs.git/blob - src/runtime/PythonPorts.cxx
Salome HOME
2da1567aee06078f98a15ef0c1e0669aef238cc1
[modules/yacs.git] / src / runtime / PythonPorts.cxx
1 // Copyright (C) 2006-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PythonPorts.hxx"
21 #include "TypeConversions.hxx"
22 #include "TypeCode.hxx"
23 #include "Node.hxx"
24 #include "ConversionException.hxx"
25
26 #include <iostream>
27 #include <sstream>
28
29 //#define _DEVDEBUG_
30 #include "YacsTrace.hxx"
31
32 using namespace YACS::ENGINE;
33 using namespace std;
34
35 void releasePyObj(PyObject* data)
36 {
37   DEBTRACE( "data refcnt: " << data->ob_refcnt );
38   if (PyObject_HasAttrString(data, (char*)"_is_a"))
39     {
40       PyObject *result = PyObject_CallMethod(data, (char*)"_is_a", (char*)"s",(char*)"IDL:SALOME/GenericObj:1.0");
41       if(result && PyLong_Check(result))
42         {
43           if(PyLong_AS_LONG(result))
44             {
45               PyObject* o=PyObject_CallMethod(data, (char*)"Destroy", (char*)"");
46               if(o)
47                 Py_XDECREF( o);
48               else
49                 {
50 #ifdef _DEVDEBUG_
51                   PyErr_Print();
52 #else
53                   PyErr_Clear();
54 #endif
55                   throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
56                 }
57             }
58           Py_XDECREF(result); 
59         }
60       if(!result)
61         {
62 #ifdef _DEVDEBUG_
63           PyErr_Print();
64 #else
65           PyErr_Clear();
66 #endif
67           throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
68         }
69     }
70 }
71
72 void registerPyObj(PyObject* data)
73 {
74   if (PyObject_HasAttrString(data, (char*)"_is_a"))
75     {
76       PyObject *result = PyObject_CallMethod(data, (char*)"_is_a", (char*)"s",(char*)"IDL:SALOME/GenericObj:1.0");
77       if(result && PyLong_Check(result))
78         {
79           if(PyLong_AS_LONG(result))
80             {
81               PyObject* o= PyObject_CallMethod(data, (char*)"Register", (char*)"") ;
82               if(o)
83                 Py_XDECREF( o);
84               else
85                 {
86 #ifdef _DEVDEBUG_
87                   PyErr_Print();
88 #else
89                   PyErr_Clear();
90 #endif
91                   throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
92                 }
93             }
94           Py_XDECREF(result); 
95         }
96       if(!result)
97         {
98 #ifdef _DEVDEBUG_
99           PyErr_Print();
100 #else
101           PyErr_Clear();
102 #endif
103           throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
104         }
105     }
106 }
107
108 InputPyPort::InputPyPort(const std::string& name, Node *node, TypeCode * type)
109   : InputPort(name, node, type)
110   , DataPort(name, node, type)
111   , Port(node)
112   , _data(Py_None)
113   ,_initData(Py_None)
114   ,_isEmpty(true)
115 {
116   Py_INCREF(_data);
117   Py_INCREF(_initData);
118 }
119 InputPyPort::~InputPyPort()
120 {
121   PyGILState_STATE gstate = PyGILState_Ensure();
122   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
123   DEBTRACE( "_initData refcnt: " << _initData->ob_refcnt );
124   // Release or not release : all GenericObj are deleted when the input port is deleted
125   releasePyObj(_data);
126   Py_XDECREF(_data); 
127   Py_XDECREF(_initData); 
128   PyGILState_Release(gstate);
129 }
130
131 InputPyPort::InputPyPort(const InputPyPort& other, Node *newHelder):InputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
132 {
133   _initData=other._initData;
134   Py_INCREF(_initData);
135   _data=other._data;
136   Py_INCREF(_data);
137   _isEmpty=other._isEmpty;
138 }
139
140 bool InputPyPort::edIsManuallyInitialized() const
141 {
142   return _initData!=Py_None;
143 }
144
145 void InputPyPort::edRemoveManInit()
146 {
147   Py_XDECREF(_initData);
148   _initData=Py_None;
149   Py_INCREF(_initData);
150   Py_XDECREF(_data);
151   _data=Py_None;
152   Py_INCREF(_data);
153   _isEmpty=true;
154   InputPort::edRemoveManInit();
155 }
156
157 void InputPyPort::put(const void *data) throw(ConversionException)
158 {
159   put((PyObject *)data);
160 }
161
162 void InputPyPort::put(PyObject *data) throw(ConversionException)
163 {
164   InterpreterUnlocker l;
165   releasePyObj(_data);
166   Py_XDECREF(_data); 
167   _data = data;
168   _stringRef="";
169   Py_INCREF(_data); 
170   registerPyObj(_data);
171   _isEmpty=false;
172   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
173 }
174
175 InputPort *InputPyPort::clone(Node *newHelder) const
176 {
177   return new InputPyPort(*this,newHelder);
178 }
179
180 PyObject * InputPyPort::getPyObj() const
181 {
182   return _data;
183 }
184
185 void *InputPyPort::get() const throw(YACS::Exception)
186 {
187   return (void*) _data;
188 }
189
190 std::string InputPyPort::getAsString()
191 {
192   std::string ret;
193   //protect _data against modification or delete in another thread
194   PyObject* data=_data;
195   Py_INCREF(data);
196   ret = convertPyObjectToString(data);
197   Py_XDECREF(data);
198   return ret;
199 }
200
201 std::string InputPyPort::getHumanRepr()
202 {
203   if(!_data)
204     return dump();
205   PyObject *ret(PyObject_Str(_data));
206   if(!ret)
207     return dump();
208   std::string retCpp;
209   char *val(PyBytes_AsString(ret));
210   if(val)
211     retCpp=val;
212   Py_XDECREF(ret);
213   return retCpp;
214 }
215
216 bool InputPyPort::isEmpty()
217 {
218   return _isEmpty;
219 }
220
221 //! Save the current data value for further reinitialization of the port
222 /*!
223  *
224  */
225 void InputPyPort::exSaveInit()
226 {
227   // Interpreter lock seems necessary when deleting lists in Python 2.7
228   PyGILState_STATE gstate = PyGILState_Ensure();
229   Py_XDECREF(_initData);
230   PyGILState_Release(gstate);
231   _initData=_data;
232   Py_INCREF(_initData); 
233   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
234   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
235 }
236
237 //! Restore the saved data value to current data value
238 /*!
239  * If no data has been saved (_initData == 0) don't restore
240  */
241 void InputPyPort::exRestoreInit()
242 {
243   if(!_initData)return;
244   Py_XDECREF(_data); 
245   _data=_initData;
246   Py_INCREF(_data);
247   _isEmpty = false;
248   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
249   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
250 }
251
252 std::string InputPyPort::dump()
253 {
254   if( _data == Py_None)
255     return "<value>None</value>";
256
257   InterpreterUnlocker l;
258   if (edGetType()->kind() != YACS::ENGINE::Objref)
259     return convertPyObjectXml(edGetType(), _data);
260   if (! _stringRef.empty())
261     return _stringRef;
262   else 
263     return convertPyObjectXml(edGetType(), _data);
264 //     {
265 //       stringstream msg;
266 //       msg << "Cannot retreive init reference string for port " << _name
267 //           << " on node " << _node->getName();
268 //       throw Exception(msg.str());      
269 //     }
270 }
271
272 std::string InputPyPort::valToStr()
273 {
274   int isString = PyBytes_Check(getPyObj());
275   //DEBTRACE("isString=" << isString);
276   PyObject *strPyObj = PyObject_Str(getPyObj());
277   //DEBTRACE(PyString_Size(strPyObj));
278   string val = PyBytes_AsString(strPyObj);
279   if (isString)
280     val = "\"" + val + "\"";
281   //DEBTRACE(val);
282   Py_DECREF(strPyObj);
283   return val;
284 }
285
286 void InputPyPort::valFromStr(std::string valstr)
287 {
288 }
289
290
291 OutputPyPort::OutputPyPort(const std::string& name, Node *node, TypeCode * type)
292   : OutputPort(name, node, type), DataPort(name, node, type), Port(node)
293 {
294   _data = Py_None;
295   Py_INCREF(_data); 
296 }
297 OutputPyPort::~OutputPyPort()
298 {
299   PyGILState_STATE gstate = PyGILState_Ensure();
300   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
301   // Release or not release : all GenericObj are deleted when the output port is deleted
302   releasePyObj(_data);
303   Py_XDECREF(_data); 
304   PyGILState_Release(gstate);
305 }
306
307 OutputPyPort::OutputPyPort(const OutputPyPort& other, Node *newHelder):OutputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder),
308                                                                        _data(Py_None)
309 {
310   Py_INCREF(_data);
311 }
312
313 void OutputPyPort::put(const void *data) throw(ConversionException)
314 {
315   put((PyObject *)data);
316 }
317
318 void OutputPyPort::put(PyObject *data) throw(ConversionException)
319 {
320   InputPort *p;
321   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
322 #ifdef _DEVDEBUG_
323   PyObject_Print(data,stderr,Py_PRINT_RAW);
324   cerr << endl;
325 #endif
326   releasePyObj(_data);
327   Py_XDECREF(_data); 
328   _data = data;
329   Py_INCREF(_data); 
330   //no registerPyObj : we steal the output reference of the node
331   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
332   OutputPort::put(data);
333 }
334
335 OutputPort *OutputPyPort::clone(Node *newHelder) const
336 {
337   return new OutputPyPort(*this,newHelder);
338 }
339
340 PyObject * OutputPyPort::get() const
341 {
342   return _data;
343 }
344
345 PyObject * OutputPyPort::getPyObj() const
346 {
347   return _data;
348 }
349
350 std::string OutputPyPort::getAsString()
351 {
352   std::string ret;
353   //protect _data against modification or delete in another thread
354   PyObject* data=_data;
355   Py_INCREF(data); 
356   ret = convertPyObjectToString(data);
357   Py_XDECREF(data); 
358   return ret;
359 }
360
361 std::string OutputPyPort::dump()
362 {
363   if( _data == Py_None)
364     return "<value>None</value>";
365   InterpreterUnlocker l;
366   string xmldump = convertPyObjectXml(edGetType(), _data);
367   return xmldump;
368 }
369
370 std::string OutputPyPort::valToStr()
371 {
372   PyObject *strPyObj = PyObject_Str(getPyObj());
373   string val = PyBytes_AsString(strPyObj);
374   Py_DECREF(strPyObj);
375   return val;
376 }
377
378 void OutputPyPort::valFromStr(std::string valstr)
379 {
380 }