Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / runtime / SalomePythonNode.cxx
1 #include "RuntimeSALOME.hxx"
2 #include "SalomePythonComponent.hxx"
3 #include "SalomePythonNode.hxx"
4 #include "PythonNode.hxx"
5 #include "PythonPorts.hxx"
6 #include "CORBANode.hxx"
7 #include "TypeCode.hxx"
8
9 #include <iostream>
10 #include <sstream>
11
12 using namespace YACS::ENGINE;
13 using namespace std;
14
15 const char SalomePythonNode::PLACEMENT_VAR_NAME_IN_INTERP[]="__container__from__YACS__";
16
17 SalomePythonNode::SalomePythonNode(const SalomePythonNode& other, ComposedNode *father):ServiceInlineNode(other,father),_pyfunc(0),_context(0)
18 {
19   //Not a bug : just because port point of view this is like PythonNode.
20   _implementation = PythonNode::IMPL_NAME;
21   PyGILState_STATE gstate = PyGILState_Ensure();
22   _context=PyDict_New();
23   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
24     {
25       stringstream msg;
26       msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
27       PyGILState_Release(gstate);
28       throw Exception(msg.str());
29     }
30   PyGILState_Release(gstate);
31 }
32
33 SalomePythonNode::SalomePythonNode(const std::string& name): ServiceInlineNode(name),_pyfunc(0)
34 {
35
36   //Not a bug : just because port point of view this is like PythonNode.
37   _implementation = PythonNode::IMPL_NAME;
38   PyGILState_STATE gstate = PyGILState_Ensure();
39   _context=PyDict_New();
40   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
41     {
42       stringstream msg;
43       msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
44       PyGILState_Release(gstate);
45       throw Exception(msg.str());
46     }
47   PyGILState_Release(gstate);
48 }
49
50 void SalomePythonNode::load()
51 {
52   ServiceInlineNode::load();
53   cerr << "---------------SalomePythonNode::load function---------------" << endl;
54   list<OutputPort *>::iterator iter;
55   string value2Export=((SalomePythonComponent*)_component)->getStringValueToExportInInterp();
56   PyObject* ob=PyString_FromString(value2Export.c_str());
57   PyDict_SetItemString(_context,PLACEMENT_VAR_NAME_IN_INTERP,ob);
58   for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
59     {
60       OutputPyPort *p=(OutputPyPort *)*iter;
61       cerr << "port name: " << p->getName() << endl;
62       cerr << "port kind: " << p->edGetType()->kind() << endl;
63     }
64   cerr <<  _script << endl;
65   PyGILState_STATE gstate = PyGILState_Ensure();
66   PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context);
67   if(res == NULL)
68     {
69       PyErr_Print();
70       PyGILState_Release(gstate);
71       throw Exception("Error during execution");
72       return;
73     }
74   Py_DECREF(res);
75   _pyfunc=PyDict_GetItemString(_context,_method.c_str());
76   if(_pyfunc == NULL)
77     {
78       PyErr_Print();
79       PyGILState_Release(gstate);
80       throw Exception("Error during execution");
81     }
82   cerr << "---------------End SalomePythonNode::load function---------------" << endl;
83   PyGILState_Release(gstate);
84 }
85
86 void SalomePythonNode::execute()
87 {
88   cerr << "++++++++++++++ SalomePythonNode::execute: " << getName() << " ++++++++++++++++++++" << endl;
89   int pos=0;
90   PyObject* ob;
91   if(!_pyfunc)throw Exception("SalomePythonNode badly loaded");
92   PyGILState_STATE gstate = PyGILState_Ensure();
93   
94   cerr << "---------------SalomePythonNode::inputs---------------" << endl;
95   PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
96   list<InputPort *>::iterator iter2;
97   for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
98     {
99       InputPyPort *p=(InputPyPort *)*iter2;
100       cerr << "port name: " << p->getName() << endl;
101       cerr << "port kind: " << p->edGetType()->kind() << endl;
102       ob=p->getPyObj();
103       PyObject_Print(ob,stderr,Py_PRINT_RAW);
104       cerr << endl;
105       cerr << "ob refcnt: " << ob->ob_refcnt << endl;
106       Py_INCREF(ob);
107       PyTuple_SetItem(args,pos,ob);
108       cerr << "ob refcnt: " << ob->ob_refcnt << endl;
109       pos++;
110     }
111   cerr << "---------------End SalomePythonNode::inputs---------------" << endl;
112
113   cerr << "----------------SalomePythonNode::calculation---------------" << endl;
114   PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
115   cerr << endl;
116   PyObject_Print(args,stderr,Py_PRINT_RAW);
117   cerr << endl;
118   PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
119   Py_DECREF(args);
120   if(result == NULL)
121     {
122       PyErr_Print();
123       PyGILState_Release(gstate);
124       throw Exception("Error during execution");
125     }
126   cerr << "----------------End SalomePythonNode::calculation---------------" << endl;
127
128   cerr << "-----------------SalomePythonNode::outputs-----------------" << endl;
129   int nres=1;
130   if(result == Py_None)
131     nres=0;
132   else if(PyTuple_Check(result))
133     nres=PyTuple_Size(result);
134
135   if(getNumberOfOutputPorts() != nres)
136     {
137       Py_DECREF(result);
138       PyGILState_Release(gstate);
139       throw Exception("Number of output arguments : Mismatch between definition and execution");
140     }
141
142   pos=0;
143   PyObject_Print(result,stderr,Py_PRINT_RAW);
144   cerr << endl;
145   list<OutputPort *>::iterator iter;
146   try
147     {
148       for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
149         {
150           OutputPyPort *p=(OutputPyPort *)*iter;
151           cerr << "port name: " << p->getName() << endl;
152           cerr << "port kind: " << p->edGetType()->kind() << endl;
153           cerr << "port pos : " << pos << endl;
154           if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
155           else ob=result;
156           cerr << "ob refcnt: " << ob->ob_refcnt << endl;
157           PyObject_Print(ob,stderr,Py_PRINT_RAW);
158           cerr << endl;
159           p->put(ob);
160           pos++;
161         }
162     }
163   catch(ConversionException)
164     {
165       Py_DECREF(result);
166       PyGILState_Release(gstate);
167       throw;
168     }
169   cerr << "-----------------End SalomePythonNode::outputs-----------------" << endl;
170
171   Py_DECREF(result);
172   PyGILState_Release(gstate);
173   cerr << "++++++++++++++ End SalomePythonNode::execute: " << getName() << " ++++++++++++++++++++" << endl;
174 }
175
176 std::string SalomePythonNode::getKind() const
177 {
178   //This not a bug !!! Returns SalomeNode::KIND to be managed by SalomeContainer.
179   return SalomeNode::KIND;
180 }
181
182 Node *SalomePythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
183 {
184   return new SalomePythonNode(*this,father);
185 }
186
187 ServiceNode *SalomePythonNode::createNode(const std::string &name)
188 {
189   ServiceNode* node=new SalomePythonNode(name);
190   node->setComponent(_component);
191   return node;
192 }
193
194 //! Create a new node of same type with a given name
195 SalomePythonNode* SalomePythonNode::cloneNode(const std::string& name)
196 {
197   SalomePythonNode* n=new SalomePythonNode(name);
198   n->setScript(_script);
199   n->setMethod(_method);
200   list<InputPort *>::iterator iter;
201   for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
202     {
203       InputPyPort *p=(InputPyPort *)*iter;
204       n->edAddInputPort(p->getName(),p->edGetType());
205     }
206   list<OutputPort *>::iterator iter2;
207   for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
208     {
209       OutputPyPort *p=(OutputPyPort *)*iter2;
210       n->edAddOutputPort(p->getName(),p->edGetType());
211     }
212   return n;
213 }