nghiduong90
nghiduong90

Reputation: 107

Converting C++ object to python object in cython?

I am having a hard time with my first cython program, so please don't discourage me if I have a stupid question.

This is my example:

c_foo.h:

// c_foo.h
class foo:
{
    public:
        ....

        std::unique_ptr<2DVector> get_cFoo_unique_ptr(); // Vec2D<T> is a vector of vectors of T
                                                         // std::vector<std::vector<T>>

    private:
        std::unique_ptr<Vec2D> cFoo_unique_ptr; // Vec2D<T> is a vector of vectors of T
}

foo.pyx: # foo.pyx import cython ... # other import from cython.operator cimport unique_ptr as cpp_unique_ptr

cdef extern from c_foo.h:
    cdef cppclass c_foo:
        ...

        cpp_unique_ptr get_cFoo_unique_ptr()


cdef class py_foo:
    cdef c_foo* cFoo

    ...

    def get_Vec2D(self):
        return self.cFoo.get_cFoo_unique_ptr().get()

So, what I am trying to do here is getting data from C++ unique_ptr and return them in python. And cython complains about it.

def get_Vec2D(self):
    return self.cFoo.get_cFoo_unique_ptr().get()
----------------------------------------------------------
 foo.pyx:xx:xx: Cannot convert 'T *' to Python object   

Another attempt is that I try other way to declare cython unique_ptr of vectors:

# foo.pyx
import cython
... # other import
from cython.memory cimport unique_ptr as cpp_unique_ptr
from cython.vector cimport vector as cpp_vector

cdef extern from c_foo.h:
    cdef cppclass c_foo:
        ...

        cpp_unique_ptr[cpp_vector[cpp_vector[T]]] get_cFoo_unique_ptr()


cdef class py_foo:
    cdef c_foo* cFoo

    ...

    def get_Vec2D(self):
        return self.cFoo.get_cFoo_unique_ptr().get()

And still the same error:

Cannot convert 'vector[vector[T]] *' to Python object

So, my question is how can I access the data of C++ unique_ptr in cython? And is there any good practice that I should know for passing data between C++ and python via cython?

Thanks

Upvotes: 2

Views: 2095

Answers (1)

Paul Cornelius
Paul Cornelius

Reputation: 11009

This kind of thing confused me for a long time. I have only used Cython in a C environment, not C++, so I don't know about other options that might exist in your case. But I'll explain how I do it, and hope that will be helpful.

You must create Python objects at the end of your Cython function, since those are the only valid return values. That means, among other things, that you can't return a pointer or a C array. For example, suppose I have a Cython function f that calculates a double array:

def f():
    cdef double aa[1000]
    cdef int i
    # ....
    # some calculation that populates aa
    # ....
    # Now I can't just return aa because aa isn't a Python object.
    # I have to convert it to a Python list:
    a = []
    for i in range(1000):
        a.append(aa[i])  # Cython knows how convert one C float to one Python float
    return a

Upvotes: 1

Related Questions