// Copyright (C) 2006-2024 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // %include std_except.i %include std_string.i %include std_map.i %include std_list.i %include std_vector.i %include std_set.i // ---------------------------------------------------------------------------- %{ #include "yacsconfig.h" #ifdef OMNIORB #include #include omniORBpyAPI* api=0; #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS \ catch (const CORBA::SystemException& ex) { \ return api->handleCxxSystemException(ex); \ } #else #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS #endif #include "Node.hxx" #include "InlineNode.hxx" #include "ComposedNode.hxx" #include "ServiceNode.hxx" #include "ServiceInlineNode.hxx" #include "ServerNode.hxx" #include "Proc.hxx" #include "Bloc.hxx" #include "ForLoop.hxx" #include "WhileLoop.hxx" #include "ForEachLoop.hxx" #include "Switch.hxx" #include "InputPort.hxx" #include "OutputPort.hxx" #include "InPropertyPort.hxx" #include "InputDataStreamPort.hxx" #include "OutputDataStreamPort.hxx" #include "OptimizerLoop.hxx" #include "HomogeneousPoolContainer.hxx" #include "IteratorPy3.hxx" #include class InterpreterUnlocker { public: InterpreterUnlocker() { _save = PyEval_SaveThread(); // allow Python threads to run } ~InterpreterUnlocker() { PyEval_RestoreThread(_save); // restore the thread state } private: PyThreadState *_save; }; static PyObject* convertNode(YACS::ENGINE::Node* node,int owner=0) { if (!node) return SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Node,owner); PyObject * ob; //should use $descriptor(YACS::ENGINE::Bloc *) and so on but $descriptor is not defined here // It is better to define a helper function to avoid code bloat // First try to find a swig type info by its mangled name std::string swigtypename="_p_"+node->typeName(); swig_type_info *ret = SWIG_MangledTypeQuery(swigtypename.c_str()); if (ret) ob=SWIG_NewPointerObj((void*)node,ret,owner); else { //typeName not known by swig. Try dynamic_cast on known classes //You must respect inheritance order in casting : Bloc before ComposedNode and so on if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Proc,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Bloc,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ForLoop,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__WhileLoop,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ForEachLoop,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Switch,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ComposedNode,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__InlineFuncNode,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__InlineNode,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServiceInlineNode,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServiceNode,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServerNode,owner); else if(dynamic_cast(node)) ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ElementaryNode,owner); else ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Node,owner); } return ob; } static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0) { if(!port) return SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__Port, owner); PyObject * ob; std::string swigtypename="_p_"+port->typeName(); swig_type_info *ret = SWIG_MangledTypeQuery(swigtypename.c_str()); if (ret) { YACS::ENGINE::InPropertyPort *inpropertyport = dynamic_cast(port); if(inpropertyport) return SWIG_NewPointerObj((void*)inpropertyport,ret,owner); YACS::ENGINE::InputPort *inport = dynamic_cast(port); if(inport) return SWIG_NewPointerObj((void*)inport,ret,owner); YACS::ENGINE::OutputPort *outport = dynamic_cast(port); if(outport) return SWIG_NewPointerObj((void*)outport,ret,owner); YACS::ENGINE::InputDataStreamPort *indsport = dynamic_cast(port); if(indsport) return SWIG_NewPointerObj((void*)indsport,ret,owner); YACS::ENGINE::OutputDataStreamPort *outdsport = dynamic_cast(port); if(outdsport) return SWIG_NewPointerObj((void*)outdsport,ret,owner); return SWIG_NewPointerObj((void*)port,ret,owner); } else { if(YACS::ENGINE::AnyInputPort *cport =dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)cport,SWIGTYPE_p_YACS__ENGINE__AnyInputPort,owner); else if(YACS::ENGINE::AnyOutputPort *cport =dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)cport,SWIGTYPE_p_YACS__ENGINE__AnyOutputPort,owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InPropertyPort,owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InputPort,owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutputPort,owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InputDataStreamPort, owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutputDataStreamPort, owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InPort, owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutPort, owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InGate, owner); else if(dynamic_cast(port)) ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutGate, owner); else ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__Port, owner); } return ob; } static PyObject *convertContainer(YACS::ENGINE::Container *cont, int owner=0) { if(!cont) return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner); if(dynamic_cast(cont)) { return SWIG_NewPointerObj((void*)dynamic_cast(cont),SWIGTYPE_p_YACS__ENGINE__HomogeneousPoolContainer, owner); } return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner); } //convertFromPyObjVectorOfObj(pyLi,SWIGTYPE_p_YACS__ENGINE__SequenceAny,"SequenceAny") template static void convertFromPyObjVectorOfObj(PyObject *pyLi, swig_type_info *ty, const char *typeStr, typename std::vector& ret) { void *argp=0; if(PyList_Check(pyLi)) { int size=PyList_Size(pyLi); ret.resize(size); for(int i=0;i(argp); ret[i]=arg; } } else if(PyTuple_Check(pyLi)) { int size=PyTuple_Size(pyLi); ret.resize(size); for(int i=0;i(argp); ret[i]=arg; } } else if(SWIG_IsOK(SWIG_ConvertPtr(pyLi,&argp,ty,0|0))) { ret.resize(1); T arg=reinterpret_cast< T >(argp); ret[0]=arg; } else throw YACS::Exception("convertFromPyObjVectorOfObj : not a list nor a tuple"); } %} // ---------------------------------------------------------------------------- #if SWIG_VERSION >= 0x010329 %template() std::list; %template() std::list; #else #ifdef SWIGPYTHON %typemap(out) std::list { int i; std::list::iterator iL; $result = PyList_New($1.size()); for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) PyList_SetItem($result,i,PyLong_FromLong((*iL))); } %typemap(out) std::list { int i; std::list::iterator iL; $result = PyList_New($1.size()); for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) PyList_SetItem($result,i,PyUnicode_FromString((*iL).c_str())); } %typemap(in) std::list { /* Check if input is a list */ if (PyList_Check($input)) { int size = PyList_Size($input); int i = 0; std::list myList; $1 = myList; for (i = 0; i < size; i++) { PyObject *o = PyList_GetItem($input,i); if (PyUnicode_Check(o)) $1.push_back(std::string(PyUnicode_AsUTF8(PyList_GetItem($input,i)))); else { PyErr_SetString(PyExc_TypeError,"list must contain strings"); return NULL; } } } else { PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; } } #endif #endif // ---------------------------------------------------------------------------- #ifdef SWIGPYTHON %typecheck(SWIG_TYPECHECK_POINTER) YACS::ENGINE::Any* { void *ptr; if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0) == 0) $1 = 1; else if (PyLong_Check($input)) $1 = 1; else if(PyFloat_Check($input)) $1 = 1; else if (PyUnicode_Check($input)) $1 = 1; else if (PyBytes_Check($input)) $1 = 1; else $1 = 0; } %typemap(in) YACS::ENGINE::Any* (int is_new_object) { if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,SWIG_POINTER_EXCEPTION)) == 0) { // It is an Any : it is converted by SWIG_ConvertPtr $input -> $1 is_new_object=0; } else if (PyLong_Check($input)) { // It is an Int $1=YACS::ENGINE::AtomAny::New((int)PyLong_AsLong($input)); is_new_object=1; } else if(PyFloat_Check($input)) { // It is a Float $1=YACS::ENGINE::AtomAny::New(PyFloat_AsDouble($input)); is_new_object=1; } else if(PyUnicode_Check($input)) { // It is a Unicode $1=YACS::ENGINE::AtomAny::New(PyUnicode_AsUTF8($input)); is_new_object=1; } else if(PyBytes_Check($input)) { // It is a Bytes Py_ssize_t len(0); char *pt(nullptr); PyBytes_AsStringAndSize($input,&pt,&len); $1=YACS::ENGINE::AtomAny::New(std::string(pt,len)); is_new_object=1; } else { // It is an error PyErr_SetString(PyExc_TypeError,"not a yacs any or a convertible type"); return NULL; } } %typemap(directorout) YACS::ENGINE::Any* { if ((SWIG_ConvertPtr($1,(void **) &$result, $1_descriptor,SWIG_POINTER_EXCEPTION)) == 0) { // It is an Any : it is converted by SWIG_ConvertPtr $input -> $1 } else if (PyInt_Check($1)) { // It is an Int $result=YACS::ENGINE::AtomAny::New((int)PyLong_AsLong($1)); } else if(PyFloat_Check($1)) { // It is a Float $result=YACS::ENGINE::AtomAny::New(PyFloat_AsDouble($1)); } else if(PyUnicode_Check($1)) { // It is a Unicode $result=YACS::ENGINE::AtomAny::New(PyUnicode_AsUTF8($1)); } else if(PyBytes_Check($1)) { // It is a Bytes Py_ssize_t len(0); char *pt(nullptr); PyBytes_AsStringAndSize($1,&pt,&len); $result=YACS::ENGINE::AtomAny::New(std::string(pt,len)); } else { // It is an error PyErr_SetString(PyExc_TypeError,"not a yacs any or a convertible type"); return NULL; } } %typemap(freearg) YACS::ENGINE::Any *inSample { //a reference is taken by the routine called if (!is_new_object$argnum) $1->incrRef(); } %typemap(freearg) YACS::ENGINE::Any* { //no reference taken by the routine called if (is_new_object$argnum) $1->decrRef(); } %typemap(out) YACS::ENGINE::Any* { if(dynamic_cast($1)) $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__SequenceAny,$owner); else if(dynamic_cast($1)) $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__ArrayAny,$owner); else if(dynamic_cast($1)) $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__StructAny,$owner); else $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__Any,$owner); } %typemap(out) YACS::ENGINE::TypeCode* { if(dynamic_cast($1)) $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeStruct,$owner); else if(dynamic_cast($1)) $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeSeq,$owner); else if(dynamic_cast($1)) $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCodeObjref,$owner); else $result=SWIG_NewPointerObj((void*)$1,SWIGTYPE_p_YACS__ENGINE__TypeCode,$owner); } %typemap(in) std::list { // Check if input is a list if (PyList_Check($input)) { int size = PyList_Size($input); int i = 0; std::list myList; $1 = myList; for (i = 0; i < size; i++) { PyObject *o = PyList_GetItem($input,i); YACS::ENGINE::TypeCode* temp; if ((SWIG_ConvertPtr(o, (void **) &temp, $descriptor(YACS::ENGINE::TypeCode*),0)) == -1) { PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCode*"); return NULL; } else { if(temp->kind() == YACS::ENGINE::Objref) $1.push_back((YACS::ENGINE::TypeCodeObjref*)temp); else { PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCodeObjref*"); return NULL; } } } } else { PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; } } %typemap(in) const std::list& { if(!PyList_Check($input)) { PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; } $1=new std::list; int size(PyList_Size($input)); for(int i=0;ipush_back(temp); } } %typemap(out) YACS::ENGINE::Node* { $result=convertNode($1,$owner); } %typemap(out) YACS::ENGINE::ServiceNode* { $result=convertNode($1,$owner); } %typemap(out) YACS::ENGINE::InlineNode* { $result=convertNode($1,$owner); } %typemap(out) YACS::ENGINE::InlineFuncNode* { $result=convertNode($1,$owner); } %typemap(out) YACS::ENGINE::ComposedNode* { $result=convertNode($1,$owner); } %typemap(out) YACS::ENGINE::OptimizerLoop* { $result=convertNode($1,$owner); } %typemap(out) YACS::ENGINE::Proc* { $result=convertNode($1,$owner); } %typemap(out) std::set { int i; std::set::iterator iL; $result = PyList_New($1.size()); PyObject * ob; for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) { ob=convertNode(*iL); PyList_SetItem($result,i,ob); } } %typemap(out) std::list { int i; std::list::iterator iL; $result = PyList_New($1.size()); PyObject * ob; for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) { ob=convertNode(*iL); PyList_SetItem($result,i,ob); } } %typemap(out) YACS::ENGINE::InputPort*,YACS::ENGINE::OutputPort*,YACS::ENGINE::InPort*,YACS::ENGINE::OutPort*,YACS::ENGINE::InPropertyPort* { $result=convertPort($1,$owner); } %typemap(out) std::set { int i; std::set::iterator iL; $result = PyList_New($1.size()); PyObject * ob; for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) { ob=convertPort(*iL); PyList_SetItem($result,i,ob); } } %typemap(out) std::set { int i; std::set::iterator iL; $result = PyList_New($1.size()); PyObject * ob; for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) { ob=convertPort(*iL); PyList_SetItem($result,i,ob); } } %typemap(out) std::set { std::set::iterator iL; $result = PyList_New(0); PyObject * ob; int status; for (iL=$1.begin(); iL!=$1.end(); iL++) { ob=convertPort(*iL); status=PyList_Append($result,ob); Py_DECREF(ob); if (status < 0) { PyErr_SetString(PyExc_TypeError,"cannot build the inport list"); return NULL; } } } %typemap(out) std::set { std::set::iterator iL; $result = PyList_New(0); PyObject * ob; int status; for (iL=$1.begin(); iL!=$1.end(); iL++) { ob=convertPort(*iL); status=PyList_Append($result,ob); Py_DECREF(ob); if (status < 0) { PyErr_SetString(PyExc_TypeError,"cannot build the outport list"); return NULL; } } } %typemap(out) std::list { std::list::const_iterator it; $result = PyTuple_New($1.size()); int i = 0; for (it = $1.begin(); it != $1.end(); ++it, ++i) { PyTuple_SetItem($result,i,convertPort(*it)); } } %typemap(out) std::list { std::list::const_iterator it; $result = PyTuple_New($1.size()); int i = 0; for (it = $1.begin(); it != $1.end(); ++it, ++i) { PyTuple_SetItem($result,i,convertPort(*it)); } } %typemap(out) std::list { std::list::const_iterator it; $result = PyTuple_New($1.size()); int i = 0; for (it = $1.begin(); it != $1.end(); ++it, ++i) { PyTuple_SetItem($result,i,convertPort(*it)); } } %typemap(out) std::list { std::list::const_iterator it; $result = PyTuple_New($1.size()); int i = 0; for (it = $1.begin(); it != $1.end(); ++it, ++i) { PyTuple_SetItem($result,i,convertPort(*it)); } } %typemap(out) std::list { std::list::const_iterator it; $result = PyTuple_New($1.size()); int i = 0; for (it = $1.begin(); it != $1.end(); ++it, ++i) { PyTuple_SetItem($result,i,convertPort(*it)); } } %typemap(out) std::vector< std::list > { std::vector< std::list >::const_iterator it; $result = PyList_New($1.size()); int i(0); for (it = $1.begin(); it != $1.end(); ++it, ++i) { const std::list& elt(*it); PyObject *tmp(PyList_New(elt.size())); int j(0); for (auto it2=elt.begin() ; it2!= elt.end() ; ++it2, ++j) PyList_SetItem(tmp,j,convertNode(*it2)); PyList_SetItem($result,i,tmp); } } #endif // ---------------------------------------------------------------------------- /* * Exception section */ // a general exception handler %exception { try { $action } catch(YACS::Exception& _e) { PyErr_SetString(PyExc_ValueError,_e.what()); return NULL; } catch(std::invalid_argument& _e) { PyErr_SetString(PyExc_IOError ,_e.what()); return NULL; } catch (std::domain_error& e) { SWIG_exception(SWIG_ValueError, e.what() ); } catch (std::overflow_error& e) { SWIG_exception(SWIG_OverflowError, e.what() ); } catch (std::out_of_range& e) { PyErr_SetString(PyExc_KeyError,e.what()); return NULL; } catch (std::length_error& e) { SWIG_exception(SWIG_IndexError, e.what() ); } catch (std::runtime_error& e) { SWIG_exception(SWIG_RuntimeError, e.what() ); } OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS catch (std::exception& e) { SWIG_exception(SWIG_SystemError, e.what() ); } catch(...) { SWIG_exception(SWIG_UnknownError, "Unknown exception"); } } // a specific exception handler = generic + release lock %define PYEXCEPTION(name) %exception name { try { InterpreterUnlocker _l; $action } catch(YACS::Exception& _e) { PyErr_SetString(PyExc_ValueError,_e.what()); return NULL; } catch(std::invalid_argument& _e) { PyErr_SetString(PyExc_IOError ,_e.what()); return NULL; } catch (std::domain_error& e) { SWIG_exception(SWIG_ValueError, e.what() ); } catch (std::overflow_error& e) { SWIG_exception(SWIG_OverflowError, e.what() ); } catch (std::out_of_range& e) { PyErr_SetString(PyExc_KeyError,e.what()); return NULL; } catch (std::length_error& e) { SWIG_exception(SWIG_IndexError, e.what() ); } catch (std::runtime_error& e) { SWIG_exception(SWIG_RuntimeError, e.what() ); } OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS catch (std::exception& e) { SWIG_exception(SWIG_SystemError, e.what() ); } catch(...) { SWIG_exception(SWIG_UnknownError, "Unknown exception"); } } %enddef %define EXCEPTION(name) %exception name { try { $action } catch(YACS::Exception& _e) { PyErr_SetString(PyExc_ValueError,_e.what()); return NULL; } catch(std::invalid_argument& _e) { PyErr_SetString(PyExc_IOError ,_e.what()); return NULL; } catch (std::domain_error& e) { SWIG_exception(SWIG_ValueError, e.what() ); } catch (std::overflow_error& e) { SWIG_exception(SWIG_OverflowError, e.what() ); } catch (std::out_of_range& e) { PyErr_SetString(PyExc_KeyError,e.what()); return NULL; } catch (std::length_error& e) { SWIG_exception(SWIG_IndexError, e.what() ); } catch (std::runtime_error& e) { SWIG_exception(SWIG_RuntimeError, e.what() ); } OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS catch (std::exception& e) { SWIG_exception(SWIG_SystemError, e.what() ); } catch(...) { SWIG_exception(SWIG_UnknownError, "Unknown exception"); } } %enddef /* * End of Exception section */ // ---------------------------------------------------------------------------- /* * Ownership section */ //Release ownership : transfer it to C++ %apply SWIGTYPE *DISOWN { YACS::ENGINE::CatalogLoader* factory}; %apply SWIGTYPE *DISOWN { YACS::ENGINE::Node *DISOWNnode }; %apply SWIGTYPE *DISOWN { Node *DISOWNnode }; /* * End of ownership section */ /* * Reference counting section * reference counted objects are created with a count of 1 so we do not incrRef them on wrapping creation * we only decrRef them on wrapping destruction. * Do not forget to declare them new (%newobject) when they are not returned from a constructor * unless they will not be decrRef on wrapping destruction */ %feature("ref") YACS::ENGINE::RefCounter "" %feature("unref") YACS::ENGINE::RefCounter "$this->decrRef();" // Unfortunately, class ComponentInstance inherits from RefCounter AND PropertyInterface. Thus the ref and // unref features are ambiguous and with swig 2.0.7 at least, we must re-specify those features for class // ComponentInstance unless the instances are destroyed when the Swig object is unref'ed. %feature("ref") YACS::ENGINE::ComponentInstance "" %feature("unref") YACS::ENGINE::ComponentInstance "$this->decrRef();" /* * End of Reference counting section */ // ---------------------------------------------------------------------------- /* %wrapper %{ namespace swig { template <> struct traits_from { static PyObject *from(YACS::ENGINE::InPort* val){ return convertPort(val); } }; template <> struct traits_from { static PyObject *from(YACS::ENGINE::OutPort* val) { return convertPort(val); } }; template <> struct traits_from { static PyObject *from(YACS::ENGINE::InPort* val){ return convertPort(val); } }; template <> struct traits_from { static PyObject *from(YACS::ENGINE::OutPort* val) { return convertPort(val); } }; } %} */ // ---------------------------------------------------------------------------- %include "IteratorPy3.hxx" %include "exception.i" %define REFCOUNT_TEMPLATE(tname, T) /* This macro is a special wrapping for map with value type which derives from RefCounter. To overload standard SWIG wrapping we define a full specialization of std::map with %extend for 5 basic methods : getitem, setitem, delitem, keys and iter. We also provide an iterator and %extend with the __next__ method : required in python 3. (see https://docs.python.org/3/library/stdtypes.html#iterator-types) Then we complete the interface by deriving the shadow wrapper from the python mixin class (UserDict.DictMixin / collections.MutableMapping with Python 3). Do not forget to declare the new shadow class to SWIG with tname_swigregister(tname). Objects returned by __getitem__ are declared new (%newobject) so that when destroyed they call decrRef (see feature("unref") for RefCounter). */ %exception IteratorPy3::__next__ { try { $action // calls %extend function next() below } catch (StopIteratorPy3) { PyErr_SetString(PyExc_StopIteration, "End of iterator"); return NULL; } } %extend IteratorPy3 { // std::pair& __next__() std::string __next__() { if ($self->cur != $self->end) { // dereference the iterator and return reference to the object, // after that it increments the iterator //return *self->cur++; std::string key= self->cur->first; *self->cur++; return key; } throw StopIteratorPy3(); } } template<> class std::map { public: %extend { void __setitem__(const std::string& name, T* c) { std::map::iterator i = self->find(name); if (i != self->end()) { if(c==i->second) return; i->second->decrRef(); } (*self)[name]=c; c->incrRef(); } T* __getitem__(std::string name) { std::map::iterator i = self->find(name); if (i != self->end()) { i->second->incrRef(); return i->second; } else throw std::out_of_range("key not found"); } void __delitem__(std::string name) { std::map::iterator i = self->find(name); if (i != self->end()) { i->second->decrRef(); self->erase(i); } else throw std::out_of_range("key not found"); } PyObject* keys() { int pysize = self->size(); PyObject* keyList = PyList_New(pysize); std::map::const_iterator i = self->begin(); for (int j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(keyList, j, PyUnicode_FromString(i->first.c_str())); } return keyList; } IteratorPy3 __iter__() { // return a constructed IteratorPy3 object return IteratorPy3($self->begin(), $self->end()); } int __len__() { int pysize = self->size(); return pysize; } } }; %newobject std::map::__getitem__; %newobject std::map::__iter__; %template(tname##it) IteratorPy3; %template() std::pair; %template(tname) std::map; %pythoncode { from collections.abc import MutableMapping class tname(tname,MutableMapping):pass import sys sys.modules['_'+__name__].##tname##_swigregister(tname) } %enddef