title: How to convert Python object to a std::vector of Cython extension type and back?
body: <p>I use Cython to wrap C++ code. The code contains a function defined as:</p>
  
  <pre><code>std::vector&lt;ClassOut&gt; analyze(std::vector&lt;ClassIn&gt; inputVec);
  </code></pre>
  
  <p>ClassIn and ClassOut are extension types. From Python I'd like to be able to call this function with a list or a numpy array (whatever is possible and most sensible). I also want to be able to access and modify the extenion types, so something like this:</p>
  
  <p>run.py</p>
  
  <pre><code>from cythonCode.classIn import PyClassIn
  from cythonCode.classOut import PyClassOut
  from cythonCode.analyze import PyAnalyze
  
  classIn_list = []
  classIn_list.append(PyClassIn())
  classIn_list.append(PyClassIn())
  classOut_list = PyAnalyze(classIn_list)
  print(classOut_list)
  </code></pre>
  
  <p>The wrappers PyClassIn and PyClassOut work fine. The problem is simply the wrapping of the analyze function from the beginning. My version of the wrapper PyAnalyze can be found below:</p>
  
  <p>analyze.pxd</p>
  
  <pre><code>from libcpp.vector cimport vector
  from classOut cimport ClassOut
  from classIn cimport ClassIn, PyClassIn
  
  cdef extern from "../cppCode/analyze.h":
    vector[ClassOut] analyze(vector[ClassIn])
  </code></pre>
  
  <p>analyze.pyx</p>
  
  <pre><code>def PyAnalyze(vector&lt;PyClassIn&gt; inputVec)
    return analyze(inputVec)
  </code></pre>
  
  <p>There are for sure mistakes in the analyze.pyx. I am getting the error:</p>
  
  <pre><code>Python object type 'PyClassIn' cannot be used as a template argument
  </code></pre>
  
  <p>The return statement has to be incorrect as well. Cython complains with:</p>
  
  <pre><code>Cannot convert 'vector[ClassOut]' to Python object
  </code></pre>
  
  <p>I have this code as a minimal example at <a href="https://github.com/zyzzler/cython-vector-minimal-example.git" rel="nofollow noreferrer">https://github.com/zyzzler/cython-vector-minimal-example.git</a></p>
  
  <p><strong>EDIT</strong>: Thanks to your input I am now at the point where the return type of the definition can be wrapped but the argument not yet. The link in the first comment provided great information about getting the return type correct. So assuming I'd want to wrap a function defined as:</p>
  
  <pre><code>std::vector&lt;ClassOut&gt; analyze(std::vector&lt;float&gt; inputVec);
  </code></pre>
  
  <p>everything works fine! However, I have to deal with the Extension Type ClassIn in place of float. So below is the code I have now:</p>
  
  <p>analyze.pyx</p>
  
  <pre><code>def PyAnalyze(classesIn):
    cdef vector[ClassOut] classesOut = analyze(classesIn)
  
    retval = PyClassOutVector()
    retval.move_from(move(classesOut))
  
    return retval
  </code></pre>
  
  <p>The above code throws the error:</p>
  
  <pre><code>Cannot convert Python object to 'vector[ClassIn]'
  </code></pre>
  
  <p>The reason for this error is clear. "classesIn" is a Python list of PyClassIn objects but analyze(...) takes a vector[ClassIn] as input. So the question is how to convert from the Python list to the std::vector and/or from PyClassIn to ClassIn? I tried to use the rvalue reference and move constructor formalism as well but it didn't work. I also tried to do it via a function like this:</p>
  
  <pre><code>cdef vector[ClassIn] list_to_vec(classInList):
    cdef vector[ClassIn] classInVec
    for classIn in classInList:
      classInVec.push_back(&lt;ClassIn&gt;classIn)
    return classInVec
  </code></pre>
  
  <p>The problem here is the <code>&lt;ClassIn&gt;classIn</code> statement. It says:</p>
  
  <pre><code>no matching function for call to 'ClassIn::ClassIn(PyObject*&amp;)'
  </code></pre>
  
  <p>So I am really puzzled here. How could this be solved? I adapted the code with the minimal example in the git I posted above.</p>
  
  <p><strong>EDIT2</strong>: To provide some more information for the comments below. I now have a wrapper for <code>PyClassInVector</code> exactly like the one for <code>PyClassOutVector</code>, see below:</p>
  
  <pre><code>cdef class PyClassInVector:
    cdef vector[ClassIn] vec
  
    cdef move_from(self, vector[ClassIn]&amp;&amp; move_this):
      self.vec = move(move_this)
  
    def __getitem__(self, idx):
      return PyClassIn2(self, idx)
  
    def __len__(self):
      return self.vec.size()
  
  cdef class PyClassIn2:
    cdef ClassIn* thisptr
    cdef PyClassInVector vector
  
    def __cinit__(self, PyClassInVector vec, idx):
      self.vector = vec
      self.thisptr = &amp;vec.vec[idx]
  </code></pre>
  
  <p>In <code>analyze.pxd</code> I also added:</p>
  
  <pre><code>cdef extern from "&lt;utility&gt;":
    vector[ClassIn]&amp;&amp; move(vector[ClassIn]&amp;&amp;)
  </code></pre>
  
  <p>Now based on the comments, in the <code>PyAnalyze</code>function I'd do:</p>
  
  <pre><code>def PyAnalyze(classesIn):
    # classesIn is a list of PyClassIn objects and needs to be converted to a PyClassInVector
    classInVec = PyClassInVector()
    cdef vector[ClassOut] classesOut = analyze(classInVec.vec)
  
    retval = PyClassOutVector()
    retval.move_from(move(classesOut))
  
    return retval
  </code></pre>
  
  <p>But as the comment in the code says, how can I get the list of PyClassIn objects (classesIn) into the PyClassInVector (classInVec)?</p>
  
  <p><strong>EDIT3</strong>: Imagine <code>PyClassOut</code> is decorated with an attribute that can be set via the constructor:</p>
  
  <pre><code>cdef class PyClassOut()
    def __cinit__(self, number):
      self.classOut_c = ClassOut(number)
  
    @property
    def number(self):
      return self.classOut_c.number
  </code></pre>
  
  <p>In <code>run.py</code> I'm doing something like this:</p>
  
  <pre><code>from cythonCode.classIn import PyClassIn
  from cythonCode.classOut import PyClassOut
  from cythonCode.analyze import PyAnalyze
  
  classIn_list = []
  classIn_list.append(PyClassIn(1))
  classIn_list.append(PyClassIn(2))
  
  classOut_list = PyAnalyze(classIn_list)
  
  print(classOut_list[0].number)
  print(classOut_list[1].number)
  </code></pre>
  
  <p><code>classOut_list</code> is essentially the <code>retvalue</code> from the <code>PyAnalyze</code> function. The retvalue is a <code>PyClassOutVector</code> object. So <code>classOut_list[0]</code> gives me the <code>PyClassOut2</code> object at the index 0. But here I don't have access to the attribute <code>number</code>. Also what I notice is that the address of <code>classOut_list[1]</code> is the same as the one of <code>classOut_list[0]</code>. I don't understand this. I am not entirely sure what 'move' does. Also I actually want to have a python list again as the <code>retvalue</code>, ideally with <code>PyClassOut</code> objects instead of the <code>PyClassOut2</code> objects. Does that make sense? And is it feasible?</p>