cython use class wrapper pointer

I’m new to cython and maybe i’m missing some base info, so be patient. What i want to do is create a c++ object in python, modify it and return the object’s pointer to a c++ function. Basically i have:

// headers.h

class A {
    A();
    void modifyA()
}

class B {
    B();
    void useA(A *a);
}
# headers.pxd

cdef extern from "headers.h":
    cdef cppclass A:
        void modifyA()

    cdef cppclass B:
        void useA(A *a)
# PyA.pyx

cdef class PyA:
    cdef A *pa

    def __cinit__(self):
        self.pa = new A()

    def modifyA(self):
        self.pa.modifyA()

Now, as far as i understand, when i instantiate PyA from python code, an A object is created in c++ and a pointer is stored inside the new PyA object. What i want to do is use that pointer like:

# PyB.pyx

cdef class PyB:
    cdef B *b

    def __cinit__(self):
        self.b = new B()

    def useA(self, pyA: PyA):
        self.b.useA(pyA.pa)

but it gives me “Cannot convert Python object to ‘A *'” and i can’t understand why… Is there something i’m missing?

Answer

The “Cannot convert Python object to ‘Something'” error in Cython generally means Cython is not detecting the type of an object/property, and thus believes it will be a Python object, only available at runtime.

That being said, you have to make sure Cython understands the type. In your particular case, you can choose between:

  • Having a single .pyx (merging both .pyx files), for cython to be able to directly determine that pyA.pa is of type A*.
  • Declaring a “cython header file” or .pxd file, which will work much like a .h file in C++ by declaring types of objects, functions and classes.

The second case would look like this:

# PyA.pxd
cdef class PyA:
    cdef A *pa
# PyB.pyx
from PyA cimport PyA    # import the PyA class from PyA.pxd definition
cdef class PyB:
# [...]