Salome HOME
Merge remote-tracking branch 'origin/master' into V9_dev
[modules/yacs.git] / src / runtime / PythonPorts.cxx
1 // Copyright (C) 2006-2016  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), DataPort(name, node, type), Port(node), _data(Py_None),_initData(Py_None)
110 {
111   Py_INCREF(_data);
112   Py_INCREF(_initData);
113 }
114 InputPyPort::~InputPyPort()
115 {
116   PyGILState_STATE gstate = PyGILState_Ensure();
117   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
118   DEBTRACE( "_initData refcnt: " << _initData->ob_refcnt );
119   // Release or not release : all GenericObj are deleted when the input port is deleted
120   releasePyObj(_data);
121   Py_XDECREF(_data); 
122   Py_XDECREF(_initData); 
123   PyGILState_Release(gstate);
124 }
125
126 InputPyPort::InputPyPort(const InputPyPort& other, Node *newHelder):InputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
127 {
128   _initData=other._initData;
129   Py_INCREF(_initData);
130   _data=other._data;
131   Py_INCREF(_data);
132 }
133
134 bool InputPyPort::edIsManuallyInitialized() const
135 {
136   return _initData!=Py_None;
137 }
138
139 void InputPyPort::edRemoveManInit()
140 {
141   Py_XDECREF(_initData);
142   _initData=Py_None;
143   Py_INCREF(_initData);
144   Py_XDECREF(_data);
145   _data=Py_None;
146   Py_INCREF(_data);
147   InputPort::edRemoveManInit();
148 }
149
150 void InputPyPort::put(const void *data) throw(ConversionException)
151 {
152   put((PyObject *)data);
153 }
154
155 void InputPyPort::put(PyObject *data) throw(ConversionException)
156 {
157   InterpreterUnlocker l;
158   releasePyObj(_data);
159   Py_XDECREF(_data); 
160   _data = data;
161   _stringRef="";
162   Py_INCREF(_data); 
163   registerPyObj(_data);
164   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
165 }
166
167 InputPort *InputPyPort::clone(Node *newHelder) const
168 {
169   return new InputPyPort(*this,newHelder);
170 }
171
172 PyObject * InputPyPort::getPyObj() const
173 {
174   return _data;
175 }
176
177 void *InputPyPort::get() const throw(YACS::Exception)
178 {
179   return (void*) _data;
180 }
181
182 std::string InputPyPort::getAsString()
183 {
184   std::string ret;
185   //protect _data against modification or delete in another thread
186   PyObject* data=_data;
187   Py_INCREF(data);
188   ret = convertPyObjectToString(data);
189   Py_XDECREF(data);
190   return ret;
191 }
192
193 std::string InputPyPort::getHumanRepr()
194 {
195   if(!_data)
196     return dump();
197   PyObject *ret(PyObject_Str(_data));
198   if(!ret)
199     return dump();
200   std::string retCpp;
201   char *val(PyBytes_AsString(ret));
202   if(val)
203     retCpp=val;
204   Py_XDECREF(ret);
205   return retCpp;
206 }
207
208 bool InputPyPort::isEmpty()
209 {
210   return _data == Py_None;
211 }
212
213 //! Save the current data value for further reinitialization of the port
214 /*!
215  *
216  */
217 void InputPyPort::exSaveInit()
218 {
219   // Interpreter lock seems necessary when deleting lists in Python 2.7
220   PyGILState_STATE gstate = PyGILState_Ensure();
221   Py_XDECREF(_initData);
222   PyGILState_Release(gstate);
223   _initData=_data;
224   Py_INCREF(_initData); 
225   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
226   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
227 }
228
229 //! Restore the saved data value to current data value
230 /*!
231  * If no data has been saved (_initData == 0) don't restore
232  */
233 void InputPyPort::exRestoreInit()
234 {
235   if(!_initData)return;
236   Py_XDECREF(_data); 
237   _data=_initData;
238   Py_INCREF(_data); 
239   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
240   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
241 }
242
243 std::string InputPyPort::dump()
244 {
245   if( _data == Py_None)
246     return "<value>None</value>";
247
248   InterpreterUnlocker l;
249   if (edGetType()->kind() != YACS::ENGINE::Objref)
250     return convertPyObjectXml(edGetType(), _data);
251   if (! _stringRef.empty())
252     return _stringRef;
253   else 
254     return convertPyObjectXml(edGetType(), _data);
255 //     {
256 //       stringstream msg;
257 //       msg << "Cannot retreive init reference string for port " << _name
258 //           << " on node " << _node->getName();
259 //       throw Exception(msg.str());      
260 //     }
261 }
262
263 std::string InputPyPort::valToStr()
264 {
265   int isString = PyBytes_Check(getPyObj());
266   //DEBTRACE("isString=" << isString);
267   PyObject *strPyObj = PyObject_Str(getPyObj());
268   //DEBTRACE(PyString_Size(strPyObj));
269   string val = PyBytes_AsString(strPyObj);
270   if (isString)
271     val = "\"" + val + "\"";
272   //DEBTRACE(val);
273   Py_DECREF(strPyObj);
274   return val;
275 }
276
277 void InputPyPort::valFromStr(std::string valstr)
278 {
279 }
280
281
282 OutputPyPort::OutputPyPort(const std::string& name, Node *node, TypeCode * type)
283   : OutputPort(name, node, type), DataPort(name, node, type), Port(node)
284 {
285   _data = Py_None;
286   Py_INCREF(_data); 
287 }
288 OutputPyPort::~OutputPyPort()
289 {
290   PyGILState_STATE gstate = PyGILState_Ensure();
291   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
292   // Release or not release : all GenericObj are deleted when the output port is deleted
293   releasePyObj(_data);
294   Py_XDECREF(_data); 
295   PyGILState_Release(gstate);
296 }
297
298 OutputPyPort::OutputPyPort(const OutputPyPort& other, Node *newHelder):OutputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder),
299                                                                        _data(Py_None)
300 {
301   Py_INCREF(_data);
302 }
303
304 void OutputPyPort::put(const void *data) throw(ConversionException)
305 {
306   put((PyObject *)data);
307 }
308
309 void OutputPyPort::put(PyObject *data) throw(ConversionException)
310 {
311   InputPort *p;
312   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
313 #ifdef _DEVDEBUG_
314   PyObject_Print(data,stderr,Py_PRINT_RAW);
315   cerr << endl;
316 #endif
317   releasePyObj(_data);
318   Py_XDECREF(_data); 
319   _data = data;
320   Py_INCREF(_data); 
321   //no registerPyObj : we steal the output reference of the node
322   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
323   OutputPort::put(data);
324 }
325
326 OutputPort *OutputPyPort::clone(Node *newHelder) const
327 {
328   return new OutputPyPort(*this,newHelder);
329 }
330
331 PyObject * OutputPyPort::get() const
332 {
333   return _data;
334 }
335
336 PyObject * OutputPyPort::getPyObj() const
337 {
338   return _data;
339 }
340
341 std::string OutputPyPort::getAsString()
342 {
343   std::string ret;
344   //protect _data against modification or delete in another thread
345   PyObject* data=_data;
346   Py_INCREF(data); 
347   ret = convertPyObjectToString(data);
348   Py_XDECREF(data); 
349   return ret;
350 }
351
352 std::string OutputPyPort::dump()
353 {
354   if( _data == Py_None)
355     return "<value>None</value>";
356   InterpreterUnlocker l;
357   string xmldump = convertPyObjectXml(edGetType(), _data);
358   return xmldump;
359 }
360
361 std::string OutputPyPort::valToStr()
362 {
363   PyObject *strPyObj = PyObject_Str(getPyObj());
364   string val = PyBytes_AsString(strPyObj);
365   Py_DECREF(strPyObj);
366   return val;
367 }
368
369 void OutputPyPort::valFromStr(std::string valstr)
370 {
371 }