Salome HOME
Copyrights update 2015.
[modules/yacs.git] / src / runtime / PythonPorts.cxx
1 // Copyright (C) 2006-2015  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 && PyInt_Check(result))
42         {
43           if(PyInt_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 && PyInt_Check(result))
78         {
79           if(PyInt_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 bool InputPyPort::isEmpty()
194 {
195   return _data == Py_None;
196 }
197
198 //! Save the current data value for further reinitialization of the port
199 /*!
200  *
201  */
202 void InputPyPort::exSaveInit()
203 {
204   // Interpreter lock seems necessary when deleting lists in Python 2.7
205   PyGILState_STATE gstate = PyGILState_Ensure();
206   Py_XDECREF(_initData);
207   PyGILState_Release(gstate);
208   _initData=_data;
209   Py_INCREF(_initData); 
210   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
211   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
212 }
213
214 //! Restore the saved data value to current data value
215 /*!
216  * If no data has been saved (_initData == 0) don't restore
217  */
218 void InputPyPort::exRestoreInit()
219 {
220   if(!_initData)return;
221   Py_XDECREF(_data); 
222   _data=_initData;
223   Py_INCREF(_data); 
224   DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
225   DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
226 }
227
228 std::string InputPyPort::dump()
229 {
230   if( _data == Py_None)
231     return "<value>None</value>";
232
233   InterpreterUnlocker l;
234   if (edGetType()->kind() != YACS::ENGINE::Objref)
235     return convertPyObjectXml(edGetType(), _data);
236   if (! _stringRef.empty())
237     return _stringRef;
238   else 
239     return convertPyObjectXml(edGetType(), _data);
240 //     {
241 //       stringstream msg;
242 //       msg << "Cannot retreive init reference string for port " << _name
243 //           << " on node " << _node->getName();
244 //       throw Exception(msg.str());      
245 //     }
246 }
247
248 std::string InputPyPort::valToStr()
249 {
250   int isString = PyString_Check(getPyObj());
251   //DEBTRACE("isString=" << isString);
252   PyObject *strPyObj = PyObject_Str(getPyObj());
253   //DEBTRACE(PyString_Size(strPyObj));
254   string val = PyString_AsString(strPyObj);
255   if (isString)
256     val = "\"" + val + "\"";
257   //DEBTRACE(val);
258   Py_DECREF(strPyObj);
259   return val;
260 }
261
262 void InputPyPort::valFromStr(std::string valstr)
263 {
264 }
265
266
267 OutputPyPort::OutputPyPort(const std::string& name, Node *node, TypeCode * type)
268   : OutputPort(name, node, type), DataPort(name, node, type), Port(node)
269 {
270   _data = Py_None;
271   Py_INCREF(_data); 
272 }
273 OutputPyPort::~OutputPyPort()
274 {
275   PyGILState_STATE gstate = PyGILState_Ensure();
276   DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
277   // Release or not release : all GenericObj are deleted when the output port is deleted
278   releasePyObj(_data);
279   Py_XDECREF(_data); 
280   PyGILState_Release(gstate);
281 }
282
283 OutputPyPort::OutputPyPort(const OutputPyPort& other, Node *newHelder):OutputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder),
284                                                                        _data(Py_None)
285 {
286 }
287
288 void OutputPyPort::put(const void *data) throw(ConversionException)
289 {
290   put((PyObject *)data);
291 }
292
293 void OutputPyPort::put(PyObject *data) throw(ConversionException)
294 {
295   InputPort *p;
296   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
297 #ifdef _DEVDEBUG_
298   PyObject_Print(data,stderr,Py_PRINT_RAW);
299   cerr << endl;
300 #endif
301   releasePyObj(_data);
302   Py_XDECREF(_data); 
303   _data = data;
304   Py_INCREF(_data); 
305   //no registerPyObj : we steal the output reference of the node
306   DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
307   OutputPort::put(data);
308 }
309
310 OutputPort *OutputPyPort::clone(Node *newHelder) const
311 {
312   return new OutputPyPort(*this,newHelder);
313 }
314
315 PyObject * OutputPyPort::get() const
316 {
317   return _data;
318 }
319
320 PyObject * OutputPyPort::getPyObj() const
321 {
322   return _data;
323 }
324
325 std::string OutputPyPort::getAsString()
326 {
327   std::string ret;
328   //protect _data against modification or delete in another thread
329   PyObject* data=_data;
330   Py_INCREF(data); 
331   ret = convertPyObjectToString(data);
332   Py_XDECREF(data); 
333   return ret;
334 }
335
336 std::string OutputPyPort::dump()
337 {
338   if( _data == Py_None)
339     return "<value>None</value>";
340   InterpreterUnlocker l;
341   string xmldump = convertPyObjectXml(edGetType(), _data);
342   return xmldump;
343 }
344
345 std::string OutputPyPort::valToStr()
346 {
347   PyObject *strPyObj = PyObject_Str(getPyObj());
348   string val = PyString_AsString(strPyObj);
349   Py_DECREF(strPyObj);
350   return val;
351 }
352
353 void OutputPyPort::valFromStr(std::string valstr)
354 {
355 }