Salome HOME
7337037d9ae0d6b8bda41d039e254987fca0175c
[modules/yacs.git] / src / engine_swig / engtypemaps.i
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 std_except.i
21 %include std_string.i
22 %include std_map.i
23 %include std_list.i
24 %include std_vector.i
25 %include std_set.i
26
27 // ----------------------------------------------------------------------------
28
29 %{
30 #include "yacsconfig.h"
31
32 #ifdef OMNIORB
33 #include <omniORB4/CORBA.h>
34
35 #include <omniORBpy.h>
36 omniORBpyAPI* api=0;
37
38 #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS \
39 catch (const CORBA::SystemException& ex) { \
40   return api->handleCxxSystemException(ex); \
41 }
42 #else
43 #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS 
44 #endif
45
46 #include "Node.hxx"
47 #include "InlineNode.hxx"
48 #include "ComposedNode.hxx"
49 #include "ServiceNode.hxx"
50 #include "ServiceInlineNode.hxx"
51 #include "ServerNode.hxx"
52 #include "Proc.hxx"
53 #include "Bloc.hxx"
54 #include "ForLoop.hxx"
55 #include "WhileLoop.hxx"
56 #include "ForEachLoop.hxx"
57 #include "Switch.hxx"
58 #include "InputPort.hxx"
59 #include "OutputPort.hxx"
60 #include "InPropertyPort.hxx"
61 #include "InputDataStreamPort.hxx"
62 #include "OutputDataStreamPort.hxx"
63 #include "OptimizerLoop.hxx"
64 #include "HomogeneousPoolContainer.hxx"
65 #include "IteratorPy3.hxx"
66
67 #include <sstream>
68
69 class InterpreterUnlocker
70 {
71 public:
72   InterpreterUnlocker() 
73     {
74       _save = PyEval_SaveThread(); // allow Python threads to run
75     }
76   ~InterpreterUnlocker() 
77     {
78       PyEval_RestoreThread(_save); // restore the thread state
79     }
80 private:
81   PyThreadState *_save;
82 };
83
84 static PyObject* convertNode(YACS::ENGINE::Node* node,int owner=0)
85 {
86   if (!node)
87     return SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Node,owner);
88   PyObject * ob;
89   //should use $descriptor(YACS::ENGINE::Bloc *) and so on but $descriptor is not defined here
90   // It is better to define a helper function to avoid code bloat
91   // First try to find a swig type info by its mangled name
92   std::string swigtypename="_p_"+node->typeName();
93   swig_type_info *ret = SWIG_MangledTypeQuery(swigtypename.c_str());
94   if (ret) 
95     ob=SWIG_NewPointerObj((void*)node,ret,owner);
96   else
97     {
98       //typeName not known by swig. Try dynamic_cast on known classes
99       //You must respect inheritance order in casting : Bloc before ComposedNode and so on
100       if(dynamic_cast<YACS::ENGINE::Proc *>(node))
101         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Proc,owner);
102       else if(dynamic_cast<YACS::ENGINE::Bloc *>(node))
103         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Bloc,owner);
104       else if(dynamic_cast<YACS::ENGINE::ForLoop *>(node))
105         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ForLoop,owner);
106       else if(dynamic_cast<YACS::ENGINE::WhileLoop *>(node))
107         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__WhileLoop,owner);
108       else if(dynamic_cast<YACS::ENGINE::ForEachLoop *>(node))
109         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ForEachLoop,owner);
110       else if(dynamic_cast<YACS::ENGINE::Switch *>(node))
111         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Switch,owner);
112       else if(dynamic_cast<YACS::ENGINE::ComposedNode *>(node))
113         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ComposedNode,owner);
114       else if(dynamic_cast<YACS::ENGINE::InlineFuncNode *>(node))
115         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__InlineFuncNode,owner);
116       else if(dynamic_cast<YACS::ENGINE::InlineNode *>(node))
117         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__InlineNode,owner);
118       else if(dynamic_cast<YACS::ENGINE::ServiceInlineNode *>(node))
119         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServiceInlineNode,owner);
120       else if(dynamic_cast<YACS::ENGINE::ServiceNode *>(node))
121         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServiceNode,owner);
122       else if(dynamic_cast<YACS::ENGINE::ServerNode *>(node))
123         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServerNode,owner);
124       else if(dynamic_cast<YACS::ENGINE::ElementaryNode *>(node))
125         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ElementaryNode,owner);
126       else
127         ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Node,owner);
128     }
129   return ob;
130 }
131
132 static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
133 {
134   if(!port)
135     return SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__Port, owner);
136   PyObject * ob;
137   std::string swigtypename="_p_"+port->typeName();
138   swig_type_info *ret = SWIG_MangledTypeQuery(swigtypename.c_str());
139   if (ret)
140     {
141       YACS::ENGINE::InPropertyPort *inpropertyport = dynamic_cast<YACS::ENGINE::InPropertyPort*>(port);
142       if(inpropertyport)
143         return SWIG_NewPointerObj((void*)inpropertyport,ret,owner);
144
145       YACS::ENGINE::InputPort *inport = dynamic_cast<YACS::ENGINE::InputPort *>(port);
146       if(inport)
147         return SWIG_NewPointerObj((void*)inport,ret,owner);
148
149       YACS::ENGINE::OutputPort *outport = dynamic_cast<YACS::ENGINE::OutputPort *>(port);
150       if(outport)
151         return SWIG_NewPointerObj((void*)outport,ret,owner);
152
153       YACS::ENGINE::InputDataStreamPort *indsport = dynamic_cast<YACS::ENGINE::InputDataStreamPort *>(port);
154       if(indsport)
155         return SWIG_NewPointerObj((void*)indsport,ret,owner);
156
157       YACS::ENGINE::OutputDataStreamPort *outdsport = dynamic_cast<YACS::ENGINE::OutputDataStreamPort *>(port);
158       if(outdsport)
159         return SWIG_NewPointerObj((void*)outdsport,ret,owner);
160
161       return SWIG_NewPointerObj((void*)port,ret,owner);
162     }
163   else
164     {
165       if(YACS::ENGINE::AnyInputPort *cport =dynamic_cast<YACS::ENGINE::AnyInputPort *>(port))
166         ob=SWIG_NewPointerObj((void*)cport,SWIGTYPE_p_YACS__ENGINE__AnyInputPort,owner);
167       else if(YACS::ENGINE::AnyOutputPort *cport =dynamic_cast<YACS::ENGINE::AnyOutputPort *>(port))
168         ob=SWIG_NewPointerObj((void*)cport,SWIGTYPE_p_YACS__ENGINE__AnyOutputPort,owner);
169       else if(dynamic_cast<YACS::ENGINE::InPropertyPort*>(port))
170         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InPropertyPort,owner);
171       else if(dynamic_cast<YACS::ENGINE::InputPort *>(port))
172         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InputPort,owner);
173       else if(dynamic_cast<YACS::ENGINE::OutputPort *>(port))
174         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutputPort,owner);
175       else if(dynamic_cast<YACS::ENGINE::InputDataStreamPort *>(port))
176         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InputDataStreamPort, owner);
177       else if(dynamic_cast<YACS::ENGINE::OutputDataStreamPort *>(port))
178         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutputDataStreamPort, owner);
179       else if(dynamic_cast<YACS::ENGINE::InPort *>(port))
180         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InPort, owner);
181       else if(dynamic_cast<YACS::ENGINE::OutPort *>(port))
182         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutPort, owner);
183       else if(dynamic_cast<YACS::ENGINE::InGate *>(port))
184         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InGate, owner);
185       else if(dynamic_cast<YACS::ENGINE::OutGate *>(port))
186         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutGate, owner);
187       else
188         ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__Port, owner);
189     }
190   return ob;
191 }
192
193 static PyObject *convertContainer(YACS::ENGINE::Container *cont, int owner=0)
194 {
195   if(!cont)
196     return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner);
197   if(dynamic_cast<YACS::ENGINE::HomogeneousPoolContainer *>(cont))
198     {
199       return SWIG_NewPointerObj((void*)dynamic_cast<YACS::ENGINE::HomogeneousPoolContainer *>(cont),SWIGTYPE_p_YACS__ENGINE__HomogeneousPoolContainer, owner);
200     }
201   return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner);
202 }
203
204 //convertFromPyObjVectorOfObj<YACS::ENGINE::SequenceAny *>(pyLi,SWIGTYPE_p_YACS__ENGINE__SequenceAny,"SequenceAny")
205 template<class T>
206 static void convertFromPyObjVectorOfObj(PyObject *pyLi, swig_type_info *ty, const char *typeStr, typename std::vector<T>& ret)
207 {
208   void *argp=0;
209   if(PyList_Check(pyLi))
210     {
211       int size=PyList_Size(pyLi);
212       ret.resize(size);
213       for(int i=0;i<size;i++)
214         {
215           PyObject *obj=PyList_GetItem(pyLi,i);
216           int status=SWIG_ConvertPtr(obj,&argp,ty,0|0);
217           if(!SWIG_IsOK(status))
218             {
219               std::ostringstream oss; oss << "convertFromPyObjVectorOfObj : list is excepted to contain only " << typeStr << " instances !";
220               throw YACS::Exception(oss.str());
221             }
222           T arg=reinterpret_cast< T >(argp);
223           ret[i]=arg;
224         }
225     }
226   else if(PyTuple_Check(pyLi))
227     {
228       int size=PyTuple_Size(pyLi);
229       ret.resize(size);
230       for(int i=0;i<size;i++)
231         {
232           PyObject *obj=PyTuple_GetItem(pyLi,i);
233           int status=SWIG_ConvertPtr(obj,&argp,ty,0|0);
234           if(!SWIG_IsOK(status))
235             {
236               std::ostringstream oss; oss << "convertFromPyObjVectorOfObj : tuple is excepted to contain only " << typeStr << " instances !";
237               throw YACS::Exception(oss.str());
238             }
239           T arg=reinterpret_cast< T >(argp);
240           ret[i]=arg;
241         }
242     }
243   else if(SWIG_IsOK(SWIG_ConvertPtr(pyLi,&argp,ty,0|0)))
244     {
245       ret.resize(1);
246       T arg=reinterpret_cast< T >(argp);
247       ret[0]=arg;
248     }
249   else
250     throw YACS::Exception("convertFromPyObjVectorOfObj : not a list nor a tuple");
251 }
252
253 %}
254
255 // ----------------------------------------------------------------------------
256
257 #if SWIG_VERSION >= 0x010329
258 %template()        std::list<int>;
259 %template()        std::list<std::string>;
260 #else
261
262 #ifdef SWIGPYTHON
263 %typemap(out) std::list<int>
264 {
265   int i;
266   std::list<int>::iterator iL;
267
268   $result = PyList_New($1.size());
269   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
270     PyList_SetItem($result,i,PyLong_FromLong((*iL))); 
271 }
272
273 %typemap(out) std::list<std::string>
274 {
275   int i;
276   std::list<std::string>::iterator iL;
277
278   $result = PyList_New($1.size());
279   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
280     PyList_SetItem($result,i,PyUnicode_FromString((*iL).c_str())); 
281 }
282
283 %typemap(in) std::list<std::string>
284 {
285   /* Check if input is a list */
286   if (PyList_Check($input))
287     {
288       int size = PyList_Size($input);
289       int i = 0;
290       std::list<std::string> myList;
291       $1 = myList;
292       for (i = 0; i < size; i++)
293         {
294           PyObject *o = PyList_GetItem($input,i);
295           if (PyUnicode_Check(o))
296             $1.push_back(std::string(PyUnicode_AsUTF8(PyList_GetItem($input,i))));
297           else
298             {
299               PyErr_SetString(PyExc_TypeError,"list must contain strings");
300               return NULL;
301             }
302         }
303     }
304   else
305     {
306       PyErr_SetString(PyExc_TypeError,"not a list");
307       return NULL;
308     }
309 }
310 #endif
311 #endif
312
313 // ----------------------------------------------------------------------------
314
315 #ifdef SWIGPYTHON
316
317 %typecheck(SWIG_TYPECHECK_POINTER) YACS::ENGINE::Any*
318 {
319   void *ptr;
320   if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0) == 0) 
321     $1 = 1;
322   else if (PyLong_Check($input))
323     $1 = 1;
324   else if(PyFloat_Check($input))
325     $1 = 1;
326   else if (PyUnicode_Check($input))
327     $1 = 1;
328   else if (PyBytes_Check($input))
329     $1 = 1;
330   else 
331     $1 = 0;
332 }
333
334 %typemap(in) YACS::ENGINE::Any* (int is_new_object)
335 {
336   if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,SWIG_POINTER_EXCEPTION)) == 0)
337     {
338       // It is an Any : it is converted by SWIG_ConvertPtr $input -> $1
339       is_new_object=0;
340     }
341   else if (PyLong_Check($input))
342     {
343       // It is an Int
344       $1=YACS::ENGINE::AtomAny::New((int)PyLong_AsLong($input));
345       is_new_object=1;
346     }
347   else if(PyFloat_Check($input))
348     {
349       // It is a Float
350       $1=YACS::ENGINE::AtomAny::New(PyFloat_AsDouble($input));
351       is_new_object=1;
352     }
353   else if(PyUnicode_Check($input))
354     {
355       // It is a Unicode
356       $1=YACS::ENGINE::AtomAny::New(PyUnicode_AsUTF8($input));
357       is_new_object=1;
358     }
359   else if(PyBytes_Check($input))
360     {
361       // It is a Bytes
362       $1=YACS::ENGINE::AtomAny::New(PyBytes_AsString($input));
363       is_new_object=1;
364     }
365   else
366     {
367       // It is an error
368       PyErr_SetString(PyExc_TypeError,"not a yacs any or a convertible type");
369       return NULL;
370     }
371 }
372
373 %typemap(directorout) YACS::ENGINE::Any*
374 {
375   if ((SWIG_ConvertPtr($1,(void **) &$result, $1_descriptor,SWIG_POINTER_EXCEPTION)) == 0)
376     {
377       // It is an Any : it is converted by SWIG_ConvertPtr $input -> $1
378     }
379   else if (PyInt_Check($1))
380     {
381       // It is an Int
382       $result=YACS::ENGINE::AtomAny::New((int)PyLong_AsLong($1));
383     }
384   else if(PyFloat_Check($1))
385     {
386       // It is a Float
387       $result=YACS::ENGINE::AtomAny::New(PyFloat_AsDouble($1));
388     }
389   else if(PyUnicode_Check($1))
390     {
391       // It is a Unicode
392       $result=YACS::ENGINE::AtomAny::New(PyUnicode_AsUTF8($1));
393     }
394   else if(PyBytes_Check($1))
395     {
396       // It is a Bytes
397       Py_ssize_t len(0);
398       char *pt(nullptr);
399       PyBytes_AsStringAndSize($1,&pt,&len);
400       $result=YACS::ENGINE::AtomAny::New(std::string(pt,len));
401     }
402   else
403     {
404       // It is an error
405       PyErr_SetString(PyExc_TypeError,"not a yacs any or a convertible type");
406       return NULL;
407     }
408 }
409
410 %typemap(freearg) YACS::ENGINE::Any *inSample
411 {
412   //a reference is taken by the routine called
413   if (!is_new_object$argnum) $1->incrRef();
414 }
415
416 %typemap(freearg) YACS::ENGINE::Any*
417 {
418   //no reference taken by the routine called
419   if (is_new_object$argnum) $1->decrRef();
420 }
421
422 %typemap(out) YACS::ENGINE::Any*
423 {
424   if(dynamic_cast<YACS::ENGINE::SequenceAny *>($1))
425     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__SequenceAny,$owner);
426   else if(dynamic_cast<YACS::ENGINE::ArrayAny *>($1))
427     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__ArrayAny,$owner);
428   else if(dynamic_cast<YACS::ENGINE::StructAny *>($1))
429     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__StructAny,$owner);
430   else
431     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__Any,$owner);
432 }
433
434 %typemap(out) YACS::ENGINE::TypeCode*
435 {
436   if(dynamic_cast<YACS::ENGINE::TypeCodeStruct *>($1))
437     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeStruct,$owner);
438   else if(dynamic_cast<YACS::ENGINE::TypeCodeSeq *>($1))
439     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeSeq,$owner);
440   else if(dynamic_cast<YACS::ENGINE::TypeCodeObjref *>($1))
441     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeObjref,$owner);
442   else
443     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCode,$owner);
444 }
445
446 %typemap(in) std::list<YACS::ENGINE::TypeCodeObjref*>
447 {
448   // Check if input is a list 
449   if (PyList_Check($input))
450     {
451       int size = PyList_Size($input);
452       int i = 0;
453       std::list<YACS::ENGINE::TypeCodeObjref*> myList;
454       $1 = myList;
455       for (i = 0; i < size; i++)
456         {
457           PyObject *o = PyList_GetItem($input,i);
458           YACS::ENGINE::TypeCode* temp;
459           if ((SWIG_ConvertPtr(o, (void **) &temp, $descriptor(YACS::ENGINE::TypeCode*),0)) == -1) 
460             {
461               PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCode*");
462               return NULL;
463             }
464           else
465             {
466               if(temp->kind() == YACS::ENGINE::Objref)
467                 $1.push_back((YACS::ENGINE::TypeCodeObjref*)temp);
468               else
469                 {
470                   PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCodeObjref*");
471                   return NULL;
472                 }
473             }
474         }
475     }
476   else
477     {
478       PyErr_SetString(PyExc_TypeError,"not a list");
479       return NULL;
480     }
481 }
482
483 %typemap(in) const std::list<YACS::ENGINE::Node *>& 
484 {
485   if(!PyList_Check($input))
486     {
487       PyErr_SetString(PyExc_TypeError,"not a list");
488       return NULL;
489     }
490   $1=new std::list<YACS::ENGINE::Node *>;
491   int size(PyList_Size($input));
492   for(int i=0;i<size;i++)
493     {
494       PyObject *o=PyList_GetItem($input,i);
495       YACS::ENGINE::Node *temp(nullptr);
496       if((SWIG_ConvertPtr(o,(void **)&temp, $descriptor(YACS::ENGINE::Node*),0)) == -1)
497         {
498           PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCode*");
499           return nullptr;
500         }
501       $1->push_back(temp);
502     }
503 }
504
505 %typemap(out) YACS::ENGINE::Node*
506 {
507   $result=convertNode($1,$owner);
508 }
509
510 %typemap(out) YACS::ENGINE::ServiceNode*
511 {
512   $result=convertNode($1,$owner);
513 }
514
515 %typemap(out) YACS::ENGINE::InlineNode*
516 {
517   $result=convertNode($1,$owner);
518 }
519
520 %typemap(out) YACS::ENGINE::InlineFuncNode*
521 {
522   $result=convertNode($1,$owner);
523 }
524
525 %typemap(out) YACS::ENGINE::ComposedNode*
526 {
527   $result=convertNode($1,$owner);
528 }
529
530 %typemap(out) YACS::ENGINE::OptimizerLoop*
531 {
532   $result=convertNode($1,$owner);
533 }
534
535 %typemap(out) YACS::ENGINE::Proc*
536 {
537   $result=convertNode($1,$owner);
538 }
539
540 %typemap(out) std::set<YACS::ENGINE::Node *>
541 {
542   int i;
543   std::set<YACS::ENGINE::Node *>::iterator iL;
544
545   $result = PyList_New($1.size());
546   PyObject * ob;
547   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
548     {
549       ob=convertNode(*iL);
550       PyList_SetItem($result,i,ob); 
551     }
552 }
553
554 %typemap(out) std::list<YACS::ENGINE::Node *>
555 {
556   int i;
557   std::list<YACS::ENGINE::Node *>::iterator iL;
558
559   $result = PyList_New($1.size());
560   PyObject * ob;
561   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
562     {
563       ob=convertNode(*iL);
564       PyList_SetItem($result,i,ob); 
565     }
566 }
567
568 %typemap(out) YACS::ENGINE::InputPort*,YACS::ENGINE::OutputPort*,YACS::ENGINE::InPort*,YACS::ENGINE::OutPort*,YACS::ENGINE::InPropertyPort*
569 {
570   $result=convertPort($1,$owner);
571 }
572
573 %typemap(out) std::set<YACS::ENGINE::InGate *>
574 {
575   int i;
576   std::set<YACS::ENGINE::InGate *>::iterator iL;
577   $result = PyList_New($1.size());
578   PyObject * ob;
579   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
580     {
581       ob=convertPort(*iL);
582       PyList_SetItem($result,i,ob); 
583     }
584 }
585
586 %typemap(out) std::set<YACS::ENGINE::OutGate *>
587 {
588   int i;
589   std::set<YACS::ENGINE::OutGate *>::iterator iL;
590   $result = PyList_New($1.size());
591   PyObject * ob;
592   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
593     {
594       ob=convertPort(*iL);
595       PyList_SetItem($result,i,ob); 
596     }
597 }
598
599 %typemap(out) std::set<YACS::ENGINE::InPort *>
600 {
601   std::set<YACS::ENGINE::InPort *>::iterator iL;
602   $result = PyList_New(0);
603   PyObject * ob;
604   int status;
605   for (iL=$1.begin(); iL!=$1.end(); iL++)
606     {
607       ob=convertPort(*iL);
608       status=PyList_Append($result,ob);
609       Py_DECREF(ob);
610       if (status < 0)
611         {
612           PyErr_SetString(PyExc_TypeError,"cannot build the inport list");
613           return NULL;
614         }
615     }
616 }
617
618 %typemap(out) std::set<YACS::ENGINE::OutPort *>
619 {
620   std::set<YACS::ENGINE::OutPort *>::iterator iL;
621   $result = PyList_New(0);
622   PyObject * ob;
623   int status;
624   for (iL=$1.begin(); iL!=$1.end(); iL++)
625     {
626       ob=convertPort(*iL);
627       status=PyList_Append($result,ob);
628       Py_DECREF(ob);
629       if (status < 0)
630         {
631           PyErr_SetString(PyExc_TypeError,"cannot build the outport list");
632           return NULL;
633         }
634     }
635 }
636
637 %typemap(out) std::list<YACS::ENGINE::OutPort *>
638 {
639   std::list<YACS::ENGINE::OutPort *>::const_iterator it;
640   $result = PyTuple_New($1.size());
641   int i = 0;
642   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
643     PyTuple_SetItem($result,i,convertPort(*it));
644   }
645 }
646 %typemap(out) std::list<YACS::ENGINE::InPort *>
647 {
648   std::list<YACS::ENGINE::InPort *>::const_iterator it;
649   $result = PyTuple_New($1.size());
650   int i = 0;
651   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
652     PyTuple_SetItem($result,i,convertPort(*it));
653   }
654 }
655 %typemap(out) std::list<YACS::ENGINE::OutputPort *>
656 {
657   std::list<YACS::ENGINE::OutputPort *>::const_iterator it;
658   $result = PyTuple_New($1.size());
659   int i = 0;
660   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
661     PyTuple_SetItem($result,i,convertPort(*it));
662   }
663 }
664 %typemap(out) std::list<YACS::ENGINE::InputPort *>
665 {
666   std::list<YACS::ENGINE::InputPort *>::const_iterator it;
667   $result = PyTuple_New($1.size());
668   int i = 0;
669   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
670     PyTuple_SetItem($result,i,convertPort(*it));
671   }
672 }
673 %typemap(out) std::list<YACS::ENGINE::InPropertyPort*>
674 {
675   std::list<YACS::ENGINE::InPropertyPort *>::const_iterator it;
676   $result = PyTuple_New($1.size());
677   int i = 0;
678   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
679     PyTuple_SetItem($result,i,convertPort(*it));
680   }
681 }
682
683 %typemap(out) std::vector< std::list<YACS::ENGINE::Node *> >
684 {
685   std::vector< std::list<YACS::ENGINE::Node *> >::const_iterator it;
686   $result = PyList_New($1.size());
687   int i(0);
688   for (it = $1.begin(); it != $1.end(); ++it, ++i)
689     {
690       const std::list<YACS::ENGINE::Node *>& elt(*it);
691       PyObject *tmp(PyList_New(elt.size()));
692       int j(0);
693       for (auto it2=elt.begin() ; it2!= elt.end() ; ++it2, ++j)
694         PyList_SetItem(tmp,j,convertNode(*it2));
695       PyList_SetItem($result,i,tmp);
696     }
697 }
698
699 #endif
700
701 // ----------------------------------------------------------------------------
702
703 /*
704  * Exception section
705  */
706 // a general exception handler
707 %exception {
708    try 
709    {
710       $action
711    } 
712    catch(YACS::Exception& _e) 
713    {
714       PyErr_SetString(PyExc_ValueError,_e.what());
715       return NULL;
716    } 
717    catch(std::invalid_argument& _e) 
718    {
719       PyErr_SetString(PyExc_IOError ,_e.what());
720       return NULL;
721    } catch (std::domain_error& e) {
722       SWIG_exception(SWIG_ValueError, e.what() );
723    } catch (std::overflow_error& e) {
724       SWIG_exception(SWIG_OverflowError, e.what() );
725    } catch (std::out_of_range& e) {
726       PyErr_SetString(PyExc_KeyError,e.what());
727       return NULL;
728    } catch (std::length_error& e) {
729       SWIG_exception(SWIG_IndexError, e.what() );
730    } catch (std::runtime_error& e) {
731       SWIG_exception(SWIG_RuntimeError, e.what() );
732    }
733    OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
734    catch (std::exception& e) {
735       SWIG_exception(SWIG_SystemError, e.what() );
736    }
737    catch(...) 
738    {
739      SWIG_exception(SWIG_UnknownError, "Unknown exception");
740    }
741 }
742
743 // a specific exception handler = generic + release lock
744 %define PYEXCEPTION(name)
745 %exception name {
746    try 
747    {
748       InterpreterUnlocker _l;
749       $action
750    } 
751    catch(YACS::Exception& _e) 
752    {
753       PyErr_SetString(PyExc_ValueError,_e.what());
754       return NULL;
755    }
756    catch(std::invalid_argument& _e) 
757    {
758       PyErr_SetString(PyExc_IOError ,_e.what());
759       return NULL;
760    } catch (std::domain_error& e) {
761       SWIG_exception(SWIG_ValueError, e.what() );
762    } catch (std::overflow_error& e) {
763       SWIG_exception(SWIG_OverflowError, e.what() );
764    } catch (std::out_of_range& e) {
765       PyErr_SetString(PyExc_KeyError,e.what());
766       return NULL;
767    } catch (std::length_error& e) {
768       SWIG_exception(SWIG_IndexError, e.what() );
769    } catch (std::runtime_error& e) {
770       SWIG_exception(SWIG_RuntimeError, e.what() );
771    }
772    OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
773    catch (std::exception& e) {
774       SWIG_exception(SWIG_SystemError, e.what() );
775    }
776    catch(...) 
777    {
778      SWIG_exception(SWIG_UnknownError, "Unknown exception");
779    }
780 }
781 %enddef
782
783 %define EXCEPTION(name)
784 %exception name {
785    try 
786    {
787       $action
788    } 
789    catch(YACS::Exception& _e) 
790    {
791       PyErr_SetString(PyExc_ValueError,_e.what());
792       return NULL;
793    }
794    catch(std::invalid_argument& _e) 
795    {
796       PyErr_SetString(PyExc_IOError ,_e.what());
797       return NULL;
798    } catch (std::domain_error& e) {
799       SWIG_exception(SWIG_ValueError, e.what() );
800    } catch (std::overflow_error& e) {
801       SWIG_exception(SWIG_OverflowError, e.what() );
802    } catch (std::out_of_range& e) {
803       PyErr_SetString(PyExc_KeyError,e.what());
804       return NULL;
805    } catch (std::length_error& e) {
806       SWIG_exception(SWIG_IndexError, e.what() );
807    } catch (std::runtime_error& e) {
808       SWIG_exception(SWIG_RuntimeError, e.what() );
809    }
810    OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
811    catch (std::exception& e) {
812       SWIG_exception(SWIG_SystemError, e.what() );
813    }
814    catch(...) 
815    {
816      SWIG_exception(SWIG_UnknownError, "Unknown exception");
817    }
818 }
819 %enddef
820 /*
821  * End of Exception section
822  */
823
824 // ----------------------------------------------------------------------------
825
826 /*
827  * Ownership section
828  */
829 //Release ownership : transfer it to C++
830 %apply SWIGTYPE *DISOWN { YACS::ENGINE::CatalogLoader* factory};
831 %apply SWIGTYPE *DISOWN { YACS::ENGINE::Node *DISOWNnode };
832 %apply SWIGTYPE *DISOWN { Node *DISOWNnode };
833 /*
834  * End of ownership section
835  */
836
837 /*
838  * Reference counting section
839  * reference counted objects are created with a count of 1 so we do not incrRef them on wrapping creation
840  * we only decrRef them on wrapping destruction.
841  * Do not forget to declare them new (%newobject) when they are not returned from a constructor
842  * unless they will not be decrRef on wrapping destruction
843  */
844 %feature("ref")   YACS::ENGINE::RefCounter  ""
845 %feature("unref") YACS::ENGINE::RefCounter  "$this->decrRef();"
846
847 // Unfortunately, class ComponentInstance inherits from RefCounter AND PropertyInterface. Thus the ref and
848 // unref features are ambiguous and with swig 2.0.7 at least, we must re-specify those features for class
849 // ComponentInstance unless the instances are destroyed when the Swig object is unref'ed.
850 %feature("ref")   YACS::ENGINE::ComponentInstance  ""
851 %feature("unref") YACS::ENGINE::ComponentInstance  "$this->decrRef();"
852 /*
853  * End of Reference counting section
854  */
855
856 // ----------------------------------------------------------------------------
857
858 /*
859 %wrapper %{
860   namespace swig {
861     template <> struct traits_from<YACS::ENGINE::InPort *> {
862       static PyObject *from(YACS::ENGINE::InPort* val){
863         return convertPort(val);
864       }
865     };
866     template <> struct traits_from<YACS::ENGINE::OutPort *> {
867       static PyObject *from(YACS::ENGINE::OutPort* val) {
868         return convertPort(val);
869       }
870     };
871     template <> struct traits_from<YACS::ENGINE::InputPort *> {
872       static PyObject *from(YACS::ENGINE::InPort* val){
873         return convertPort(val);
874       }
875     };
876     template <> struct traits_from<YACS::ENGINE::OutputPort *> {
877       static PyObject *from(YACS::ENGINE::OutPort* val) {
878         return convertPort(val);
879       }
880     };
881   }
882 %}
883 */
884
885 // ----------------------------------------------------------------------------
886
887 %include "IteratorPy3.hxx"
888 %include "exception.i"
889
890 %define REFCOUNT_TEMPLATE(tname, T)
891 /*
892  This macro is a special wrapping for map with value type which derives from RefCounter.
893  To overload standard SWIG wrapping we define a full specialization of std::map
894  with %extend for 5 basic methods : getitem, setitem, delitem, keys and iter.
895  We also provide an iterator and %extend with the __next__ method : required in python 3.
896  (see https://docs.python.org/3/library/stdtypes.html#iterator-types)
897  Then we complete the interface by deriving the shadow wrapper from
898  the python mixin class (UserDict.DictMixin / collections.MutableMapping with Python 3).
899  Do not forget to declare the new shadow class to SWIG with tname_swigregister(tname).
900  Objects returned by __getitem__ are declared new (%newobject) so that when destroyed they
901  call decrRef (see feature("unref") for RefCounter).
902 */
903
904 %exception IteratorPy3<T>::__next__
905 {
906   try
907   {
908     $action  // calls %extend function next() below
909   }
910   catch (StopIteratorPy3<T>)
911   {
912     PyErr_SetString(PyExc_StopIteration, "End of iterator");
913     return NULL;
914   }
915 }
916
917 %extend IteratorPy3<T>
918 {
919 //  std::pair<const std::string,T*>& __next__()
920   std::string __next__()
921   {
922     if ($self->cur != $self->end)
923     {
924       // dereference the iterator and return reference to the object,
925       // after that it increments the iterator
926       //return *self->cur++;
927       std::string key= self->cur->first;
928       *self->cur++;
929       return key;
930     }
931     throw StopIteratorPy3<T>();
932   }
933 }
934
935 template<>
936 class std::map<std::string,T*>
937 {
938 public:
939 %extend
940 {
941   void __setitem__(const std::string& name, T* c)
942     {
943       std::map<std::string, T* >::iterator i = self->find(name);
944       if (i != self->end())
945         {
946           if(c==i->second)
947             return;
948           i->second->decrRef();
949         }
950       (*self)[name]=c;
951       c->incrRef();
952     }
953   T* __getitem__(std::string name)
954     {
955       std::map<std::string, T* >::iterator i = self->find(name);
956       if (i != self->end())
957         {
958           i->second->incrRef();
959           return i->second;
960         }
961       else
962         throw std::out_of_range("key not found");
963     }
964   void __delitem__(std::string name)
965     {
966       std::map<std::string, T* >::iterator i = self->find(name);
967       if (i != self->end())
968       {
969         i->second->decrRef();
970         self->erase(i);
971       }
972       else
973         throw std::out_of_range("key not found");
974     }
975   PyObject* keys()
976     {
977       int pysize = self->size();
978       PyObject* keyList = PyList_New(pysize);
979       std::map<std::string, T* >::const_iterator i = self->begin();
980       for (int j = 0; j < pysize; ++i, ++j)
981       {
982         PyList_SET_ITEM(keyList, j, PyUnicode_FromString(i->first.c_str()));
983       }
984       return keyList;
985     }
986   IteratorPy3<T> __iter__()
987   {
988     // return a constructed IteratorPy3 object
989     return IteratorPy3<T>($self->begin(), $self->end());
990   }
991   int __len__()
992   {
993       int pysize = self->size();
994       return pysize;
995   }
996 }
997 };
998 %newobject std::map<std::string,T* >::__getitem__;
999 %newobject std::map<std::string,T* >::__iter__;
1000 %template(tname##it)  IteratorPy3<T >;
1001 %template()           std::pair<std::string, T* >;
1002 %template(tname)      std::map<std::string, T* >;
1003 %pythoncode
1004 {
1005 from collections import MutableMapping    
1006 class tname(tname,MutableMapping):pass
1007 tname##_swigregister(tname)
1008 }
1009 %enddef
1010
1011