Salome HOME
f123067eff9d3d1aa6623372d79a726fe1db1bc9
[modules/yacs.git] / src / runtime / PythonPorts.cxx
1 // Copyright (C) 2006-2020  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   if(!data)
38     return ;
39   DEBTRACE( "data refcnt: " << data->ob_refcnt );
40   if (PyObject_HasAttrString(data, (char*)"_is_a"))
41     {
42       PyObject *result = PyObject_CallMethod(data, (char*)"_is_a", (char*)"s",(char*)"IDL:SALOME/GenericObj:1.0");
43       if(result && PyLong_Check(result))
44         {
45           if(PyLong_AS_LONG(result))
46             {
47               PyObject* o=PyObject_CallMethod(data, (char*)"Destroy", (char*)"");
48               if(o)
49                 Py_XDECREF( o);
50               else
51                 {
52 #ifdef _DEVDEBUG_
53                   PyErr_Print();
54 #else
55                   PyErr_Clear();
56 #endif
57                   throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
58                 }
59             }
60           Py_XDECREF(result); 
61         }
62       if(!result)
63         {
64 #ifdef _DEVDEBUG_
65           PyErr_Print();
66 #else
67           PyErr_Clear();
68 #endif
69           throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
70         }
71     }
72 }
73
74 void registerPyObj(PyObject* data)
75 {
76   if (PyObject_HasAttrString(data, (char*)"_is_a"))
77     {
78       PyObject *result = PyObject_CallMethod(data, (char*)"_is_a", (char*)"s",(char*)"IDL:SALOME/GenericObj:1.0");
79       if(result && PyLong_Check(result))
80         {
81           if(PyLong_AS_LONG(result))
82             {
83               PyObject* o= PyObject_CallMethod(data, (char*)"Register", (char*)"") ;
84               if(o)
85                 Py_XDECREF( o);
86               else
87                 {
88 #ifdef _DEVDEBUG_
89                   PyErr_Print();
90 #else
91                   PyErr_Clear();
92 #endif
93                   throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
94                 }
95             }
96           Py_XDECREF(result); 
97         }
98       if(!result)
99         {
100 #ifdef _DEVDEBUG_
101           PyErr_Print();
102 #else
103           PyErr_Clear();
104 #endif
105           throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj");      
106         }
107     }
108 }
109
110 InputPyPort::InputPyPort(const std::string& name, Node *node, TypeCode * type)
111   : InputPort(name, node, type)
112   , DataPort(name, node, type)
113   , Port(node)
114   , _data(Py_None)
115   ,_initData(nullptr)
116   ,_isEmpty(true)
117 {
118   Py_INCREF(_data);
119 }
120 InputPyPort::~InputPyPort()
121 {
122   PyGILState_STATE gstate = PyGILState_Ensure();
123   DEBTRACE( "_data refcnt: " << (_data ? _data->ob_refcnt : -1) );
124   DEBTRACE( "_initData refcnt: " << (_initData ? _initData->ob_refcnt : -1));
125   // Release or not release : all GenericObj are deleted when the input port is deleted
126   releasePyObj(_data);
127   Py_XDECREF(_data); 
128   Py_XDECREF(_initData); 
129   PyGILState_Release(gstate);
130 }
131
132 InputPyPort::InputPyPort(const InputPyPort& other, Node *newHelder):InputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
133 {
134   _initData=other._initData;
135   Py_XINCREF(_initData);
136   _data=other._data;
137   Py_INCREF(_data);
138   _isEmpty=other._isEmpty;
139 }
140
141 bool InputPyPort::edIsManuallyInitialized() const
142 {
143   return _initData!=nullptr;
144 }
145
146 void InputPyPort::edRemoveManInit()
147 {
148   Py_XDECREF(_initData);
149   _initData=nullptr;
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)
158 {
159   put((PyObject *)data);
160 }
161
162 void InputPyPort::releaseDataUnsafe()
163 {
164   releasePyObj(_data);
165   Py_XDECREF(_data); 
166   _data = nullptr;
167 }
168
169 void InputPyPort::releaseData()
170 {
171   InterpreterUnlocker l;
172   InputPyPort::releaseDataUnsafe();
173 }
174
175 void InputPyPort::put(PyObject *data)
176 {
177   InterpreterUnlocker l;
178   InputPyPort::releaseDataUnsafe();
179   _data = data;
180   _stringRef="";
181   Py_INCREF(_data); 
182   registerPyObj(_data);
183   _isEmpty=false;
184   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
185 }
186
187 InputPort *InputPyPort::clone(Node *newHelder) const
188 {
189   return new InputPyPort(*this,newHelder);
190 }
191
192 PyObject * InputPyPort::getPyObj() const
193 {
194   return _data;
195 }
196
197 void *InputPyPort::get() const
198 {
199   return (void*) _data;
200 }
201
202 std::string InputPyPort::getAsString()
203 {
204   std::string ret;
205   //protect _data against modification or delete in another thread
206   PyObject* data=_data;
207   Py_INCREF(data);
208   ret = convertPyObjectToString(data);
209   Py_XDECREF(data);
210   return ret;
211 }
212
213 std::string InputPyPort::getHumanRepr()
214 {
215   if(!_data)
216     return dump();
217   PyObject *ret(PyObject_Str(_data));
218   if(!ret)
219     return dump();
220   std::string retCpp;
221   char *val(PyBytes_AsString(ret));
222   if(val)
223     retCpp=val;
224   Py_XDECREF(ret);
225   return retCpp;
226 }
227
228 bool InputPyPort::isEmpty()
229 {
230   return _isEmpty;
231 }
232
233 //! Save the current data value for further reinitialization of the port
234 /*!
235  *
236  */
237 void InputPyPort::exSaveInit()
238 {
239   // Interpreter lock seems necessary when deleting lists in Python 2.7
240   PyGILState_STATE gstate = PyGILState_Ensure();
241   Py_XDECREF(_initData);
242   _initData=_data;
243   Py_INCREF(_initData); 
244   PyGILState_Release(gstate);
245   DEBTRACE( "_initData.ob refcnt: " << (_initData ? _initData->ob_refcnt : -1));
246   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
247 }
248
249 //! Restore the saved data value to current data value
250 /*!
251  * If no data has been saved (_initData == 0) don't restore
252  */
253 void InputPyPort::exRestoreInit()
254 {
255   if(!_initData)return;
256   Py_XDECREF(_data); 
257   _data=_initData;
258   Py_XINCREF(_data);
259   _isEmpty = false;
260   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
261   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
262 }
263
264 std::string InputPyPort::dump()
265 {
266   if( _isEmpty)
267     return "<value>None</value>";
268
269   InterpreterUnlocker l;
270   return convertPyObjectXml(edGetType(), _data);
271 }
272
273 std::string InputPyPort::valToStr()
274 {
275   int isString = PyBytes_Check(getPyObj());
276   //DEBTRACE("isString=" << isString);
277   PyObject *strPyObj = PyObject_Str(getPyObj());
278   //DEBTRACE(PyString_Size(strPyObj));
279   string val = PyBytes_AsString(strPyObj);
280   if (isString)
281     val = "\"" + val + "\"";
282   //DEBTRACE(val);
283   Py_DECREF(strPyObj);
284   return val;
285 }
286
287 void InputPyPort::valFromStr(std::string valstr)
288 {
289 }
290
291
292 OutputPyPort::OutputPyPort(const std::string& name, Node *node, TypeCode * type)
293   : OutputPort(name, node, type), DataPort(name, node, type), Port(node)
294 {
295   _data = Py_None;
296   Py_INCREF(_data); 
297 }
298 OutputPyPort::~OutputPyPort()
299 {
300   PyGILState_STATE gstate = PyGILState_Ensure();
301   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
302   // Release or not release : all GenericObj are deleted when the output port is deleted
303   releasePyObj(_data);
304   Py_XDECREF(_data); 
305   PyGILState_Release(gstate);
306 }
307
308 OutputPyPort::OutputPyPort(const OutputPyPort& other, Node *newHelder):OutputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder),
309                                                                        _data(Py_None)
310 {
311   Py_INCREF(_data);
312 }
313
314 void OutputPyPort::put(const void *data)
315 {
316   put((PyObject *)data);
317 }
318
319 void OutputPyPort::putWithoutForward(PyObject *data)
320 {
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 }
332
333 void OutputPyPort::put(PyObject *data)
334 {
335   putWithoutForward(data);
336   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
337   OutputPort::put(data);
338 }
339
340 OutputPort *OutputPyPort::clone(Node *newHelder) const
341 {
342   return new OutputPyPort(*this,newHelder);
343 }
344
345 PyObject * OutputPyPort::get() const
346 {
347   return _data;
348 }
349
350 PyObject * OutputPyPort::getPyObj() const
351 {
352   return _data;
353 }
354
355 std::string OutputPyPort::getAsString()
356 {
357   std::string ret;
358   //protect _data against modification or delete in another thread
359   PyObject* data=_data;
360   Py_INCREF(data); 
361   ret = convertPyObjectToString(data);
362   Py_XDECREF(data); 
363   return ret;
364 }
365
366 std::string OutputPyPort::dump()
367 {
368   InterpreterUnlocker l;
369   string xmldump = convertPyObjectXml(edGetType(), _data);
370   return xmldump;
371 }
372
373 std::string OutputPyPort::valToStr()
374 {
375   PyObject *strPyObj = PyObject_Str(getPyObj());
376   string val = PyBytes_AsString(strPyObj);
377   Py_DECREF(strPyObj);
378   return val;
379 }
380
381 void OutputPyPort::valFromStr(std::string valstr)
382 {
383 }