Version: 9.16.0
PythonPorts.cxx
Go to the documentation of this file.
1// Copyright (C) 2006-2026 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"
25
26#include <iostream>
27#include <sstream>
28
29//#define _DEVDEBUG_
30#include "YacsTrace.hxx"
31
32using namespace YACS::ENGINE;
33using namespace std;
34
35static 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
74void releasePyObj(PyObject* data)
75{
76 RegisterReleasePyObj(data,"Destroy");
77}
78
79void registerPyObj(PyObject* data)
80{
81 RegisterReleasePyObj(data,"Register");
82}
83
84InputPyPort::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
106InputPyPort::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
131void 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
149void 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
166PyObject * InputPyPort::getPyObj() const
167{
168 return _data;
169}
170
171void *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
238std::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
261void InputPyPort::valFromStr(std::string valstr)
262{
263}
264
265
266OutputPyPort::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
282OutputPyPort::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
288void 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
307void 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
319PyObject * OutputPyPort::get() const
320{
321 return _data;
322}
323
324PyObject * 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
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
355void 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)