Version: 8.3.0
PythonPorts.cxx
Go to the documentation of this file.
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 && 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 }
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
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 
135 {
136  return _initData!=Py_None;
137 }
138 
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);
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 {
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 
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 
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 
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(PyString_AsString(ret));
202  if(val)
203  retCpp=val;
204  Py_XDECREF(ret);
205  return retCpp;
206 }
207 
209 {
210  return _data == Py_None;
211 }
212 
214 
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);
224  Py_INCREF(_initData);
225  DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
226  DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
227 }
228 
230 
234 {
235  if(!_initData)return;
236  Py_XDECREF(_data);
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 
249  if (edGetType()->kind() != YACS::ENGINE::Objref)
251  if (! _stringRef.empty())
252  return _stringRef;
253  else
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 
264 {
265  int isString = PyString_Check(getPyObj());
266  //DEBTRACE("isString=" << isString);
267  PyObject *strPyObj = PyObject_Str(getPyObj());
268  //DEBTRACE(PyString_Size(strPyObj));
269  string val = PyString_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 }
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
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 
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 
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>";
357  string xmldump = convertPyObjectXml(edGetType(), _data);
358  return xmldump;
359 }
360 
362 {
363  PyObject *strPyObj = PyObject_Str(getPyObj());
364  string val = PyString_AsString(strPyObj);
365  Py_DECREF(strPyObj);
366  return val;
367 }
368 
369 void OutputPyPort::valFromStr(std::string valstr)
370 {
371 }