I'm trying to expose C++ class and method to Python. Therefore I opted to use Cython to wrap the two. C++ code is a part of a catkin package, so I researched ways how to integrate Cython compilation inside catkin_make
.
In my dummy example, there's a C++ class A
, and a factory method get_a()
which returns a shared_ptr<A>
. On Cython side I created one pair of files example_a.pxd
and example_a.pyx
which wrap C++ class A
into PyA
, and c_example_a_factory.pxd
and example_a_factory.pyx
which wrap a C++ method get_a()
into a Cython method of the same name. I both import
and cimport
class PyA
from example_a
module to example_a_factory
, and it compiles nicely. However, when I try to import example_a_factory
from python, I get an error:
ImportError: No module named example_a
I found several repos that try to accomplish something similar to what I need, in regard to build process, and I followed those examples: ros_cython_example, cython_catkin_example, cython_cmake_example
You can find my example code in this repo, together with instructions on how to run it. For easier reference, I'm posting Cython files here as well:
example_a.pxd
from libcpp.memory cimport shared_ptr
cdef extern from "catkin_cython_example/example_a.hpp" namespace "example_a":
cdef cppclass A:
int get() const
cdef class PyA:
cdef shared_ptr[A] c_a # Hold a C++ instance which we're wrapping
@staticmethod
cdef inline create(shared_ptr[A] c_a):
cdef PyA py_a = PyA()
py_a.c_a = c_a
return py_a
example_a.pyx
from cython.operator cimport dereference as d
cdef class PyA:
def get(self):
cdef int v = d(self.c_a).get()
return v
c_example_a_factory.pxd
from libcpp.memory cimport shared_ptr
from example_a cimport A
cdef extern from "catkin_cython_example/example_a_factory.hpp" namespace "example_a_factory":
shared_ptr[A] get_a(int val) except +
example_a_factory.pyx
from libcpp.memory cimport shared_ptr
cimport c_example_a_factory
from example_a cimport A, PyA
from example_a import PyA
def get_a(val):
cdef shared_ptr[A] c_a = c_example_a_factory.get_a(val)
return PyA.create(c_a)
I tested putting everything inside one module, and the code works fine, but I'd rather have separate modules for easier maintainability and logic decoupling. All the help is appreciated!