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