Version: 9.15.0
PythonPorts.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2025 CEA, EDF
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 static void RegisterReleasePyObj(PyObject* data, const char *method1)
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*)method1, (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 releasePyObj(PyObject* data)
75 {
76  RegisterReleasePyObj(data,"Destroy");
77 }
78 
79 void registerPyObj(PyObject* data)
80 {
81  RegisterReleasePyObj(data,"Register");
82 }
83 
84 InputPyPort::InputPyPort(const std::string& name, Node *node, TypeCode * type)
85  : InputPort(name, node, type)
86  , DataPort(name, node, type)
87  , Port(node)
88  , _data(Py_None)
89  ,_initData(nullptr)
90  ,_isEmpty(true)
91 {
92  Py_INCREF(_data);
93 }
95 {
96  PyGILState_STATE gstate = PyGILState_Ensure();
97  DEBTRACE( "_data refcnt: " << (_data ? _data->ob_refcnt : -1) );
98  DEBTRACE( "_initData refcnt: " << (_initData ? _initData->ob_refcnt : -1));
99  // Release or not release : all GenericObj are deleted when the input port is deleted
101  Py_XDECREF(_data);
102  Py_XDECREF(_initData);
103  PyGILState_Release(gstate);
104 }
105 
106 InputPyPort::InputPyPort(const InputPyPort& other, Node *newHelder):InputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
107 {
108  _initData=other._initData;
109  Py_XINCREF(_initData);
110  _data=other._data;
111  Py_INCREF(_data);
112  _isEmpty=other._isEmpty;
113 }
114 
116 {
117  return _initData!=nullptr;
118 }
119 
121 {
122  Py_XDECREF(_initData);
123  _initData=nullptr;
124  Py_XDECREF(_data);
125  _data=Py_None;
126  Py_INCREF(_data);
127  _isEmpty=true;
129 }
130 
131 void InputPyPort::put(const void *data)
132 {
133  put((PyObject *)data);
134 }
135 
137 {
139  Py_XDECREF(_data);
140  _data = nullptr;
141 }
142 
144 {
147 }
148 
149 void InputPyPort::put(PyObject *data)
150 {
153  _data = data;
154  _stringRef="";
155  Py_INCREF(_data);
157  _isEmpty=false;
158  DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
159 }
160 
162 {
163  return new InputPyPort(*this,newHelder);
164 }
165 
166 PyObject * InputPyPort::getPyObj() const
167 {
168  return _data;
169 }
170 
171 void *InputPyPort::get() const
172 {
173  return (void*) _data;
174 }
175 
177 {
178  std::string ret;
179  //protect _data against modification or delete in another thread
180  PyObject* data=_data;
181  Py_INCREF(data);
182  ret = convertPyObjectToString(data);
183  Py_XDECREF(data);
184  return ret;
185 }
186 
188 {
189  if(!_data)
190  return dump();
191  PyObject *ret(PyObject_Str(_data));
192  if(!ret)
193  return dump();
194  std::string retCpp;
195  char *val(PyBytes_AsString(ret));
196  if(val)
197  retCpp=val;
198  Py_XDECREF(ret);
199  return retCpp;
200 }
201 
203 {
204  return _isEmpty;
205 }
206 
208 
212 {
213  // Interpreter lock seems necessary when deleting lists in Python 2.7
214  PyGILState_STATE gstate = PyGILState_Ensure();
215  Py_XDECREF(_initData);
217  Py_INCREF(_initData);
218  PyGILState_Release(gstate);
219  DEBTRACE( "_initData.ob refcnt: " << (_initData ? _initData->ob_refcnt : -1));
220  DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
221 }
222 
224 
228 {
229  if(!_initData)return;
230  Py_XDECREF(_data);
232  Py_XINCREF(_data);
233  _isEmpty = false;
234  DEBTRACE( "_initData.ob refcnt: " << _initData->ob_refcnt );
235  DEBTRACE( "_data.ob refcnt: " << _data->ob_refcnt );
236 }
237 
238 std::string InputPyPort::dump()
239 {
240  if( _isEmpty)
241  return "<value>None</value>";
242 
245 }
246 
248 {
249  int isString = PyBytes_Check(getPyObj());
250  //DEBTRACE("isString=" << isString);
251  PyObject *strPyObj = PyObject_Str(getPyObj());
252  //DEBTRACE(PyString_Size(strPyObj));
253  string val = PyBytes_AsString(strPyObj);
254  if (isString)
255  val = "\"" + val + "\"";
256  //DEBTRACE(val);
257  Py_DECREF(strPyObj);
258  return val;
259 }
260 
261 void InputPyPort::valFromStr(std::string valstr)
262 {
263 }
264 
265 
266 OutputPyPort::OutputPyPort(const std::string& name, Node *node, TypeCode * type)
267  : OutputPort(name, node, type), DataPort(name, node, type), Port(node)
268 {
269  _data = Py_None;
270  Py_INCREF(_data);
271 }
273 {
274  PyGILState_STATE gstate = PyGILState_Ensure();
275  DEBTRACE( "_data refcnt: " << _data->ob_refcnt );
276  // Release or not release : all GenericObj are deleted when the output port is deleted
278  Py_XDECREF(_data);
279  PyGILState_Release(gstate);
280 }
281 
282 OutputPyPort::OutputPyPort(const OutputPyPort& other, Node *newHelder):OutputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder),
283  _data(Py_None)
284 {
285  Py_INCREF(_data);
286 }
287 
288 void OutputPyPort::put(const void *data)
289 {
290  put((PyObject *)data);
291 }
292 
294 {
295  DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
296 #ifdef _DEVDEBUG_
297  PyObject_Print(data,stderr,Py_PRINT_RAW);
298  cerr << endl;
299 #endif
301  Py_XDECREF(_data);
302  _data = data;
303  Py_INCREF(_data);
304  //no registerPyObj : we steal the output reference of the node
305 }
306 
307 void OutputPyPort::put(PyObject *data)
308 {
309  putWithoutForward(data);
310  DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
311  OutputPort::put(data);
312 }
313 
315 {
316  return new OutputPyPort(*this,newHelder);
317 }
318 
319 PyObject * OutputPyPort::get() const
320 {
321  return _data;
322 }
323 
324 PyObject * OutputPyPort::getPyObj() const
325 {
326  return _data;
327 }
328 
330 {
331  std::string ret;
332  //protect _data against modification or delete in another thread
333  PyObject* data=_data;
334  Py_INCREF(data);
335  ret = convertPyObjectToString(data);
336  Py_XDECREF(data);
337  return ret;
338 }
339 
340 std::string OutputPyPort::dump()
341 {
343  string xmldump = convertPyObjectXml(edGetType(), _data);
344  return xmldump;
345 }
346 
348 {
349  PyObject *strPyObj = PyObject_Str(getPyObj());
350  string val = PyBytes_AsString(strPyObj);
351  Py_DECREF(strPyObj);
352  return val;
353 }
354 
355 void OutputPyPort::valFromStr(std::string valstr)
356 {
357 }
void registerPyObj(PyObject *data)
Definition: PythonPorts.cxx:79
void releasePyObj(PyObject *data)
Definition: PythonPorts.cxx:74
static void RegisterReleasePyObj(PyObject *data, const char *method1)
Definition: PythonPorts.cxx:35
#define DEBTRACE(msg)
Definition: YacsTrace.hxx:31
TypeCode * edGetType() const
Definition: DataPort.hxx:53
Base class for Input Ports.
Definition: InputPort.hxx:44
virtual void edRemoveManInit()
Removes eventually previous manual initialisation.
Definition: InputPort.cxx:140
std::string _stringRef
Definition: InputPort.hxx:90
Class for Python Ports.
Definition: PythonPorts.hxx:74
bool edIsManuallyInitialized() const
Specifies if this port has been manually set by the call of InputPort::edInit.
virtual void exSaveInit()
Save the current data value for further reinitialization of the port.
virtual void put(const void *data)
virtual PyObj * getPyObj() const
void edRemoveManInit()
Removes eventually previous manual initialisation.
InputPort * clone(Node *newHelder) const
virtual std::string getAsString()
returns port value as a string that can be used in a GUI for example
virtual void valFromStr(std::string valstr)
Allows to set data from a string representation used in user interface.
virtual std::string dump()
virtual void exRestoreInit()
Restore the saved data value to current data value.
virtual std::string valToStr()
Gives a string representation of the data, for user interfaces.
void releaseData() override
InputPyPort(const std::string &name, Node *node, TypeCode *type)
Definition: PythonPorts.cxx:84
virtual std::string getHumanRepr()
Base class for all nodes.
Definition: Node.hxx:70
virtual void put(const void *data)
Definition: OutputPort.cxx:66
virtual PyObject * get() const
virtual PyObj * getPyObj() const
void putWithoutForward(PyObject *data)
virtual std::string valToStr()
Gives a string representation of the data, for user interfaces.
virtual std::string getAsString()
returns port value as a string that can be used in a GUI for example
virtual void put(const void *data)
virtual void valFromStr(std::string valstr)
Allows to set data from a string representation used in user interface.
virtual std::string dump()
OutputPort * clone(Node *newHelder) const
OutputPyPort(const std::string &name, Node *node, TypeCode *type)
Base class for all ports.
Definition: Port.hxx:43
Base class for all type objects.
Definition: TypeCode.hxx:68
std::string convertPyObjectToString(PyObject *ob)
std::string convertPyObjectXml(const TypeCode *t, PyObject *data)