Salome HOME
try fix REFCOUNT_TEMPLATE...
[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       $result=YACS::ENGINE::AtomAny::New(PyBytes_AsString($1));
398     }
399   else
400     {
401       // It is an error
402       PyErr_SetString(PyExc_TypeError,"not a yacs any or a convertible type");
403       return NULL;
404     }
405 }
406
407 %typemap(freearg) YACS::ENGINE::Any *inSample
408 {
409   //a reference is taken by the routine called
410   if (!is_new_object$argnum) $1->incrRef();
411 }
412
413 %typemap(freearg) YACS::ENGINE::Any*
414 {
415   //no reference taken by the routine called
416   if (is_new_object$argnum) $1->decrRef();
417 }
418
419 %typemap(out) YACS::ENGINE::Any*
420 {
421   if(dynamic_cast<YACS::ENGINE::SequenceAny *>($1))
422     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__SequenceAny,$owner);
423   else if(dynamic_cast<YACS::ENGINE::ArrayAny *>($1))
424     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__ArrayAny,$owner);
425   else if(dynamic_cast<YACS::ENGINE::StructAny *>($1))
426     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__StructAny,$owner);
427   else
428     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__Any,$owner);
429 }
430
431 %typemap(out) YACS::ENGINE::TypeCode*
432 {
433   if(dynamic_cast<YACS::ENGINE::TypeCodeStruct *>($1))
434     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeStruct,$owner);
435   else if(dynamic_cast<YACS::ENGINE::TypeCodeSeq *>($1))
436     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeSeq,$owner);
437   else if(dynamic_cast<YACS::ENGINE::TypeCodeObjref *>($1))
438     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeObjref,$owner);
439   else
440     $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCode,$owner);
441 }
442
443 %typemap(in) std::list<YACS::ENGINE::TypeCodeObjref*>
444 {
445   // Check if input is a list 
446   if (PyList_Check($input))
447     {
448       int size = PyList_Size($input);
449       int i = 0;
450       std::list<YACS::ENGINE::TypeCodeObjref*> myList;
451       $1 = myList;
452       for (i = 0; i < size; i++)
453         {
454           PyObject *o = PyList_GetItem($input,i);
455           YACS::ENGINE::TypeCode* temp;
456           if ((SWIG_ConvertPtr(o, (void **) &temp, $descriptor(YACS::ENGINE::TypeCode*),0)) == -1) 
457             {
458               PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCode*");
459               return NULL;
460             }
461           else
462             {
463               if(temp->kind() == YACS::ENGINE::Objref)
464                 $1.push_back((YACS::ENGINE::TypeCodeObjref*)temp);
465               else
466                 {
467                   PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCodeObjref*");
468                   return NULL;
469                 }
470             }
471         }
472     }
473   else
474     {
475       PyErr_SetString(PyExc_TypeError,"not a list");
476       return NULL;
477     }
478 }
479
480 %typemap(out) YACS::ENGINE::Node*
481 {
482   $result=convertNode($1,$owner);
483 }
484
485 %typemap(out) YACS::ENGINE::ServiceNode*
486 {
487   $result=convertNode($1,$owner);
488 }
489
490 %typemap(out) YACS::ENGINE::InlineNode*
491 {
492   $result=convertNode($1,$owner);
493 }
494
495 %typemap(out) YACS::ENGINE::InlineFuncNode*
496 {
497   $result=convertNode($1,$owner);
498 }
499
500 %typemap(out) YACS::ENGINE::ComposedNode*
501 {
502   $result=convertNode($1,$owner);
503 }
504
505 %typemap(out) YACS::ENGINE::OptimizerLoop*
506 {
507   $result=convertNode($1,$owner);
508 }
509
510 %typemap(out) YACS::ENGINE::Proc*
511 {
512   $result=convertNode($1,$owner);
513 }
514
515 %typemap(out) std::set<YACS::ENGINE::Node *>
516 {
517   int i;
518   std::set<YACS::ENGINE::Node *>::iterator iL;
519
520   $result = PyList_New($1.size());
521   PyObject * ob;
522   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
523     {
524       ob=convertNode(*iL);
525       PyList_SetItem($result,i,ob); 
526     }
527 }
528
529 %typemap(out) std::list<YACS::ENGINE::Node *>
530 {
531   int i;
532   std::list<YACS::ENGINE::Node *>::iterator iL;
533
534   $result = PyList_New($1.size());
535   PyObject * ob;
536   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
537     {
538       ob=convertNode(*iL);
539       PyList_SetItem($result,i,ob); 
540     }
541 }
542
543 %typemap(out) YACS::ENGINE::InputPort*,YACS::ENGINE::OutputPort*,YACS::ENGINE::InPort*,YACS::ENGINE::OutPort*,YACS::ENGINE::InPropertyPort*
544 {
545   $result=convertPort($1,$owner);
546 }
547
548 %typemap(out) std::set<YACS::ENGINE::InGate *>
549 {
550   int i;
551   std::set<YACS::ENGINE::InGate *>::iterator iL;
552   $result = PyList_New($1.size());
553   PyObject * ob;
554   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
555     {
556       ob=convertPort(*iL);
557       PyList_SetItem($result,i,ob); 
558     }
559 }
560
561 %typemap(out) std::set<YACS::ENGINE::OutGate *>
562 {
563   int i;
564   std::set<YACS::ENGINE::OutGate *>::iterator iL;
565   $result = PyList_New($1.size());
566   PyObject * ob;
567   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
568     {
569       ob=convertPort(*iL);
570       PyList_SetItem($result,i,ob); 
571     }
572 }
573
574 %typemap(out) std::set<YACS::ENGINE::InPort *>
575 {
576   std::set<YACS::ENGINE::InPort *>::iterator iL;
577   $result = PyList_New(0);
578   PyObject * ob;
579   int status;
580   for (iL=$1.begin(); iL!=$1.end(); iL++)
581     {
582       ob=convertPort(*iL);
583       status=PyList_Append($result,ob);
584       Py_DECREF(ob);
585       if (status < 0)
586         {
587           PyErr_SetString(PyExc_TypeError,"cannot build the inport list");
588           return NULL;
589         }
590     }
591 }
592
593 %typemap(out) std::set<YACS::ENGINE::OutPort *>
594 {
595   std::set<YACS::ENGINE::OutPort *>::iterator iL;
596   $result = PyList_New(0);
597   PyObject * ob;
598   int status;
599   for (iL=$1.begin(); iL!=$1.end(); iL++)
600     {
601       ob=convertPort(*iL);
602       status=PyList_Append($result,ob);
603       Py_DECREF(ob);
604       if (status < 0)
605         {
606           PyErr_SetString(PyExc_TypeError,"cannot build the outport list");
607           return NULL;
608         }
609     }
610 }
611
612 %typemap(out) std::list<YACS::ENGINE::OutPort *>
613 {
614   std::list<YACS::ENGINE::OutPort *>::const_iterator it;
615   $result = PyTuple_New($1.size());
616   int i = 0;
617   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
618     PyTuple_SetItem($result,i,convertPort(*it));
619   }
620 }
621 %typemap(out) std::list<YACS::ENGINE::InPort *>
622 {
623   std::list<YACS::ENGINE::InPort *>::const_iterator it;
624   $result = PyTuple_New($1.size());
625   int i = 0;
626   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
627     PyTuple_SetItem($result,i,convertPort(*it));
628   }
629 }
630 %typemap(out) std::list<YACS::ENGINE::OutputPort *>
631 {
632   std::list<YACS::ENGINE::OutputPort *>::const_iterator it;
633   $result = PyTuple_New($1.size());
634   int i = 0;
635   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
636     PyTuple_SetItem($result,i,convertPort(*it));
637   }
638 }
639 %typemap(out) std::list<YACS::ENGINE::InputPort *>
640 {
641   std::list<YACS::ENGINE::InputPort *>::const_iterator it;
642   $result = PyTuple_New($1.size());
643   int i = 0;
644   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
645     PyTuple_SetItem($result,i,convertPort(*it));
646   }
647 }
648 %typemap(out) std::list<YACS::ENGINE::InPropertyPort*>
649 {
650   std::list<YACS::ENGINE::InPropertyPort *>::const_iterator it;
651   $result = PyTuple_New($1.size());
652   int i = 0;
653   for (it = $1.begin(); it != $1.end(); ++it, ++i) {
654     PyTuple_SetItem($result,i,convertPort(*it));
655   }
656 }
657
658 #endif
659
660 // ----------------------------------------------------------------------------
661
662 /*
663  * Exception section
664  */
665 // a general exception handler
666 %exception {
667    try 
668    {
669       $action
670    } 
671    catch(YACS::Exception& _e) 
672    {
673       PyErr_SetString(PyExc_ValueError,_e.what());
674       return NULL;
675    } 
676    catch(std::invalid_argument& _e) 
677    {
678       PyErr_SetString(PyExc_IOError ,_e.what());
679       return NULL;
680    } catch (std::domain_error& e) {
681       SWIG_exception(SWIG_ValueError, e.what() );
682    } catch (std::overflow_error& e) {
683       SWIG_exception(SWIG_OverflowError, e.what() );
684    } catch (std::out_of_range& e) {
685       PyErr_SetString(PyExc_KeyError,e.what());
686       return NULL;
687    } catch (std::length_error& e) {
688       SWIG_exception(SWIG_IndexError, e.what() );
689    } catch (std::runtime_error& e) {
690       SWIG_exception(SWIG_RuntimeError, e.what() );
691    }
692    OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
693    catch (std::exception& e) {
694       SWIG_exception(SWIG_SystemError, e.what() );
695    }
696    catch(...) 
697    {
698      SWIG_exception(SWIG_UnknownError, "Unknown exception");
699    }
700 }
701
702 // a specific exception handler = generic + release lock
703 %define PYEXCEPTION(name)
704 %exception name {
705    try 
706    {
707       InterpreterUnlocker _l;
708       $action
709    } 
710    catch(YACS::Exception& _e) 
711    {
712       PyErr_SetString(PyExc_ValueError,_e.what());
713       return NULL;
714    }
715    catch(std::invalid_argument& _e) 
716    {
717       PyErr_SetString(PyExc_IOError ,_e.what());
718       return NULL;
719    } catch (std::domain_error& e) {
720       SWIG_exception(SWIG_ValueError, e.what() );
721    } catch (std::overflow_error& e) {
722       SWIG_exception(SWIG_OverflowError, e.what() );
723    } catch (std::out_of_range& e) {
724       PyErr_SetString(PyExc_KeyError,e.what());
725       return NULL;
726    } catch (std::length_error& e) {
727       SWIG_exception(SWIG_IndexError, e.what() );
728    } catch (std::runtime_error& e) {
729       SWIG_exception(SWIG_RuntimeError, e.what() );
730    }
731    OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
732    catch (std::exception& e) {
733       SWIG_exception(SWIG_SystemError, e.what() );
734    }
735    catch(...) 
736    {
737      SWIG_exception(SWIG_UnknownError, "Unknown exception");
738    }
739 }
740 %enddef
741
742 %define EXCEPTION(name)
743 %exception name {
744    try 
745    {
746       $action
747    } 
748    catch(YACS::Exception& _e) 
749    {
750       PyErr_SetString(PyExc_ValueError,_e.what());
751       return NULL;
752    }
753    catch(std::invalid_argument& _e) 
754    {
755       PyErr_SetString(PyExc_IOError ,_e.what());
756       return NULL;
757    } catch (std::domain_error& e) {
758       SWIG_exception(SWIG_ValueError, e.what() );
759    } catch (std::overflow_error& e) {
760       SWIG_exception(SWIG_OverflowError, e.what() );
761    } catch (std::out_of_range& e) {
762       PyErr_SetString(PyExc_KeyError,e.what());
763       return NULL;
764    } catch (std::length_error& e) {
765       SWIG_exception(SWIG_IndexError, e.what() );
766    } catch (std::runtime_error& e) {
767       SWIG_exception(SWIG_RuntimeError, e.what() );
768    }
769    OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
770    catch (std::exception& e) {
771       SWIG_exception(SWIG_SystemError, e.what() );
772    }
773    catch(...) 
774    {
775      SWIG_exception(SWIG_UnknownError, "Unknown exception");
776    }
777 }
778 %enddef
779 /*
780  * End of Exception section
781  */
782
783 // ----------------------------------------------------------------------------
784
785 /*
786  * Ownership section
787  */
788 //Release ownership : transfer it to C++
789 %apply SWIGTYPE *DISOWN { YACS::ENGINE::CatalogLoader* factory};
790 %apply SWIGTYPE *DISOWN { YACS::ENGINE::Node *DISOWNnode };
791 %apply SWIGTYPE *DISOWN { Node *DISOWNnode };
792 /*
793  * End of ownership section
794  */
795
796 /*
797  * Reference counting section
798  * reference counted objects are created with a count of 1 so we do not incrRef them on wrapping creation
799  * we only decrRef them on wrapping destruction.
800  * Do not forget to declare them new (%newobject) when they are not returned from a constructor
801  * unless they will not be decrRef on wrapping destruction
802  */
803 %feature("ref")   YACS::ENGINE::RefCounter  ""
804 %feature("unref") YACS::ENGINE::RefCounter  "$this->decrRef();"
805
806 // Unfortunately, class ComponentInstance inherits from RefCounter AND PropertyInterface. Thus the ref and
807 // unref features are ambiguous and with swig 2.0.7 at least, we must re-specify those features for class
808 // ComponentInstance unless the instances are destroyed when the Swig object is unref'ed.
809 %feature("ref")   YACS::ENGINE::ComponentInstance  ""
810 %feature("unref") YACS::ENGINE::ComponentInstance  "$this->decrRef();"
811 /*
812  * End of Reference counting section
813  */
814
815 // ----------------------------------------------------------------------------
816
817 /*
818 %wrapper %{
819   namespace swig {
820     template <> struct traits_from<YACS::ENGINE::InPort *> {
821       static PyObject *from(YACS::ENGINE::InPort* val){
822         return convertPort(val);
823       }
824     };
825     template <> struct traits_from<YACS::ENGINE::OutPort *> {
826       static PyObject *from(YACS::ENGINE::OutPort* val) {
827         return convertPort(val);
828       }
829     };
830     template <> struct traits_from<YACS::ENGINE::InputPort *> {
831       static PyObject *from(YACS::ENGINE::InPort* val){
832         return convertPort(val);
833       }
834     };
835     template <> struct traits_from<YACS::ENGINE::OutputPort *> {
836       static PyObject *from(YACS::ENGINE::OutPort* val) {
837         return convertPort(val);
838       }
839     };
840   }
841 %}
842 */
843
844 // ----------------------------------------------------------------------------
845
846 %include "IteratorPy3.hxx"
847 %include "exception.i"
848
849 %define REFCOUNT_TEMPLATE(tname, T)
850 /*
851  This macro is a special wrapping for map with value type which derives from RefCounter.
852  To overload standard SWIG wrapping we define a full specialization of std::map
853  with %extend for 5 basic methods : getitem, setitem, delitem, keys and iter.
854  We also provide an iterator and %extend with the __next__ method : required in python 3.
855  (see https://docs.python.org/3/library/stdtypes.html#iterator-types)
856  Then we complete the interface by deriving the shadow wrapper from
857  the python mixin class (UserDict.DictMixin / collections.MutableMapping with Python 3).
858  Do not forget to declare the new shadow class to SWIG with tname_swigregister(tname).
859  Objects returned by __getitem__ are declared new (%newobject) so that when destroyed they
860  call decrRef (see feature("unref") for RefCounter).
861 */
862
863 %exception IteratorPy3<T>::__next__
864 {
865   try
866   {
867     $action  // calls %extend function next() below
868   }
869   catch (StopIteratorPy3<T>)
870   {
871     PyErr_SetString(PyExc_StopIteration, "End of iterator");
872     return NULL;
873   }
874 }
875
876 %extend IteratorPy3<T>
877 {
878 //  std::pair<const std::string,T*>& __next__()
879   std::string __next__()
880   {
881     if ($self->cur != $self->end)
882     {
883       // dereference the iterator and return reference to the object,
884       // after that it increments the iterator
885       //return *self->cur++;
886       std::string key= self->cur->first;
887       *self->cur++;
888       return key;
889     }
890     throw StopIteratorPy3<T>();
891   }
892 }
893
894 template<>
895 class std::map<std::string,T*>
896 {
897 public:
898 %extend
899 {
900   void __setitem__(const std::string& name, T* c)
901     {
902       std::map<std::string, T* >::iterator i = self->find(name);
903       if (i != self->end())
904         {
905           if(c==i->second)
906             return;
907           i->second->decrRef();
908         }
909       (*self)[name]=c;
910       c->incrRef();
911     }
912   T* __getitem__(std::string name)
913     {
914       std::map<std::string, T* >::iterator i = self->find(name);
915       if (i != self->end())
916         {
917           i->second->incrRef();
918           return i->second;
919         }
920       else
921         throw std::out_of_range("key not found");
922     }
923   void __delitem__(std::string name)
924     {
925       std::map<std::string, T* >::iterator i = self->find(name);
926       if (i != self->end())
927       {
928         i->second->decrRef();
929         self->erase(i);
930       }
931       else
932         throw std::out_of_range("key not found");
933     }
934   PyObject* keys()
935     {
936       int pysize = self->size();
937       PyObject* keyList = PyList_New(pysize);
938       std::map<std::string, T* >::const_iterator i = self->begin();
939       for (int j = 0; j < pysize; ++i, ++j)
940       {
941         PyList_SET_ITEM(keyList, j, PyUnicode_FromString(i->first.c_str()));
942       }
943       return keyList;
944     }
945   IteratorPy3<T> __iter__()
946   {
947     // return a constructed IteratorPy3 object
948     return IteratorPy3<T>($self->begin(), $self->end());
949   }
950   int __len__()
951   {
952       int pysize = self->size();
953       return pysize;
954   }
955 }
956 };
957 %newobject std::map<std::string,T* >::__getitem__;
958 %newobject std::map<std::string,T* >::__iter__;
959 %template(tname##it)  IteratorPy3<T >;
960 %template()           std::pair<std::string, T* >;
961 %template(tname)      std::map<std::string, T* >;
962 %pythoncode
963 {
964 from collections import MutableMapping    
965 class tname(tname,MutableMapping):pass
966 tname##_swigregister(tname)
967 }
968 %enddef
969
970