Salome HOME
try fix REFCOUNT_TEMPLATE...
[modules/yacs.git] / src / engine_swig / engtypemaps.i
old mode 100755 (executable)
new mode 100644 (file)
index bad933f..0771a1c
@@ -1,4 +1,4 @@
-// Copyright (C) 2006-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2006-2016  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #ifdef OMNIORB
 #include <omniORB4/CORBA.h>
 
-//--- from omniORBpy.h (not present on Debian Sarge packages)
-struct omniORBPYAPI
-{
-  PyObject* (*cxxObjRefToPyObjRef)(const CORBA::Object_ptr cxx_obj,
-           CORBA::Boolean hold_lock);
-  // Convert a C++ object reference to a Python object reference.
-  // If <hold_lock> is true, caller holds the Python interpreter lock.
-
-  CORBA::Object_ptr (*pyObjRefToCxxObjRef)(PyObject* py_obj,
-             CORBA::Boolean hold_lock);
-  // Convert a Python object reference to a C++ object reference.
-  // Raises BAD_PARAM if the Python object is not an object reference.
-  // If <hold_lock> is true, caller holds the Python interpreter lock.
-
-  PyObject* (*handleCxxSystemException)(const CORBA::SystemException& ex);
-  // Sets the Python exception state to reflect the given C++ system
-  // exception. Always returns NULL. The caller must hold the Python
-  // interpreter lock.
-};
-
-omniORBPYAPI* api;
+#include <omniORBpy.h>
+omniORBpyAPI* api=0;
 
 #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS \
 catch (const CORBA::SystemException& ex) { \
@@ -80,6 +61,10 @@ catch (const CORBA::SystemException& ex) { \
 #include "InputDataStreamPort.hxx"
 #include "OutputDataStreamPort.hxx"
 #include "OptimizerLoop.hxx"
+#include "HomogeneousPoolContainer.hxx"
+#include "IteratorPy3.hxx"
+
+#include <sstream>
 
 class InterpreterUnlocker
 {
@@ -205,8 +190,70 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
   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<YACS::ENGINE::HomogeneousPoolContainer *>(cont))
+    {
+      return SWIG_NewPointerObj((void*)dynamic_cast<YACS::ENGINE::HomogeneousPoolContainer *>(cont),SWIGTYPE_p_YACS__ENGINE__HomogeneousPoolContainer, owner);
+    }
+  return SWIG_NewPointerObj((void*)cont,SWIGTYPE_p_YACS__ENGINE__Container, owner);
+}
+
+//convertFromPyObjVectorOfObj<YACS::ENGINE::SequenceAny *>(pyLi,SWIGTYPE_p_YACS__ENGINE__SequenceAny,"SequenceAny")
+template<class T>
+static void convertFromPyObjVectorOfObj(PyObject *pyLi, swig_type_info *ty, const char *typeStr, typename std::vector<T>& ret)
+{
+  void *argp=0;
+  if(PyList_Check(pyLi))
+    {
+      int size=PyList_Size(pyLi);
+      ret.resize(size);
+      for(int i=0;i<size;i++)
+        {
+          PyObject *obj=PyList_GetItem(pyLi,i);
+          int status=SWIG_ConvertPtr(obj,&argp,ty,0|0);
+          if(!SWIG_IsOK(status))
+            {
+              std::ostringstream oss; oss << "convertFromPyObjVectorOfObj : list is excepted to contain only " << typeStr << " instances !";
+              throw YACS::Exception(oss.str());
+            }
+          T arg=reinterpret_cast< T >(argp);
+          ret[i]=arg;
+        }
+    }
+  else if(PyTuple_Check(pyLi))
+    {
+      int size=PyTuple_Size(pyLi);
+      ret.resize(size);
+      for(int i=0;i<size;i++)
+        {
+          PyObject *obj=PyTuple_GetItem(pyLi,i);
+          int status=SWIG_ConvertPtr(obj,&argp,ty,0|0);
+          if(!SWIG_IsOK(status))
+            {
+              std::ostringstream oss; oss << "convertFromPyObjVectorOfObj : tuple is excepted to contain only " << typeStr << " instances !";
+              throw YACS::Exception(oss.str());
+            }
+          T arg=reinterpret_cast< T >(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<int>;
 %template()        std::list<std::string>;
@@ -230,7 +277,7 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
 
   $result = PyList_New($1.size());
   for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++)
-    PyList_SetItem($result,i,PyString_FromString((*iL).c_str())); 
+    PyList_SetItem($result,i,PyUnicode_FromString((*iL).c_str())); 
 }
 
 %typemap(in) std::list<std::string>
@@ -245,8 +292,8 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
       for (i = 0; i < size; i++)
         {
           PyObject *o = PyList_GetItem($input,i);
-          if (PyString_Check(o))
-            $1.push_back(std::string(PyString_AsString(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");
@@ -263,6 +310,8 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
 #endif
 #endif
 
+// ----------------------------------------------------------------------------
+
 #ifdef SWIGPYTHON
 
 %typecheck(SWIG_TYPECHECK_POINTER) YACS::ENGINE::Any*
@@ -270,11 +319,13 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
   void *ptr;
   if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0) == 0) 
     $1 = 1;
-  else if (PyInt_Check($input))
+  else if (PyLong_Check($input))
     $1 = 1;
   else if(PyFloat_Check($input))
     $1 = 1;
-  else if (PyString_Check($input))
+  else if (PyUnicode_Check($input))
+    $1 = 1;
+  else if (PyBytes_Check($input))
     $1 = 1;
   else 
     $1 = 0;
@@ -287,10 +338,10 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
       // It is an Any : it is converted by SWIG_ConvertPtr $input -> $1
       is_new_object=0;
     }
-  else if (PyInt_Check($input))
+  else if (PyLong_Check($input))
     {
       // It is an Int
-      $1=YACS::ENGINE::AtomAny::New((int)PyInt_AsLong($input));
+      $1=YACS::ENGINE::AtomAny::New((int)PyLong_AsLong($input));
       is_new_object=1;
     }
   else if(PyFloat_Check($input))
@@ -299,10 +350,16 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
       $1=YACS::ENGINE::AtomAny::New(PyFloat_AsDouble($input));
       is_new_object=1;
     }
-  else if(PyString_Check($input))
+  else if(PyUnicode_Check($input))
     {
-      // It is a Float
-      $1=YACS::ENGINE::AtomAny::New(PyString_AsString($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
+      $1=YACS::ENGINE::AtomAny::New(PyBytes_AsString($input));
       is_new_object=1;
     }
   else
@@ -322,17 +379,22 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
   else if (PyInt_Check($1))
     {
       // It is an Int
-      $result=YACS::ENGINE::AtomAny::New((int)PyInt_AsLong($1));
+      $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(PyString_Check($1))
+  else if(PyUnicode_Check($1))
     {
-      // It is a String
-      $result=YACS::ENGINE::AtomAny::New(PyString_AsString($1));
+      // It is a Unicode
+      $result=YACS::ENGINE::AtomAny::New(PyUnicode_AsUTF8($1));
+    }
+  else if(PyBytes_Check($1))
+    {
+      // It is a Bytes
+      $result=YACS::ENGINE::AtomAny::New(PyBytes_AsString($1));
     }
   else
     {
@@ -595,6 +657,8 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
 
 #endif
 
+// ----------------------------------------------------------------------------
+
 /*
  * Exception section
  */
@@ -716,6 +780,8 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
  * End of Exception section
  */
 
+// ----------------------------------------------------------------------------
+
 /*
  * Ownership section
  */
@@ -746,6 +812,8 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
  * End of Reference counting section
  */
 
+// ----------------------------------------------------------------------------
+
 /*
 %wrapper %{
   namespace swig {
@@ -773,17 +841,56 @@ static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0)
 %}
 */
 
-%define REFCOUNT_TEMPLATE(tname, T...)
+// ----------------------------------------------------------------------------
+
+%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 4 basic methods : getitem, setitem, delitem and keys.
+ 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).
+ 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<T>::__next__
+{
+  try
+  {
+    $action  // calls %extend function next() below
+  }
+  catch (StopIteratorPy3<T>)
+  {
+    PyErr_SetString(PyExc_StopIteration, "End of iterator");
+    return NULL;
+  }
+}
+
+%extend IteratorPy3<T>
+{
+//  std::pair<const std::string,T*>& __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<T>();
+  }
+}
+
 template<>
 class std::map<std::string,T*>
 {
@@ -816,31 +923,46 @@ public:
   void __delitem__(std::string name)
     {
       std::map<std::string, T* >::iterator i = self->find(name);
-      if (i != self->end()){
+      if (i != self->end())
+      {
         i->second->decrRef();
         self->erase(i);
       }
       else
         throw std::out_of_range("key not found");
     }
-  PyObject* keys() {
+  PyObject* keys()
+    {
       int pysize = self->size();
       PyObject* keyList = PyList_New(pysize);
       std::map<std::string, T* >::const_iterator i = self->begin();
-      for (int j = 0; j < pysize; ++i, ++j) {
-        PyList_SET_ITEM(keyList, j, PyString_FromString(i->first.c_str()));
+      for (int j = 0; j < pysize; ++i, ++j)
+      {
+        PyList_SET_ITEM(keyList, j, PyUnicode_FromString(i->first.c_str()));
       }
       return keyList;
     }
+  IteratorPy3<T> __iter__()
+  {
+    // return a constructed IteratorPy3 object
+    return IteratorPy3<T>($self->begin(), $self->end());
+  }
+  int __len__()
+  {
+      int pysize = self->size();
+      return pysize;
+  }
 }
 };
-
 %newobject std::map<std::string,T* >::__getitem__;
-%template()   std::pair<std::string, T* >;
-%template(tname)    std::map<std::string, T* >;
-%pythoncode{
-from UserDict import DictMixin
-class tname(tname,DictMixin):pass
+%newobject std::map<std::string,T* >::__iter__;
+%template(tname##it)  IteratorPy3<T >;
+%template()           std::pair<std::string, T* >;
+%template(tname)      std::map<std::string, T* >;
+%pythoncode
+{
+from collections import MutableMapping    
+class tname(tname,MutableMapping):pass
 tname##_swigregister(tname)
 }
 %enddef