My Rectangle.h
namespace shapes { class Rectangle { public: int x0, y0, x1, y1; Rectangle(); Rectangle(int x0, int y0, int x1, int y1); ~Rectangle(); int getArea(); }; }
My Rectangle.cpp
#include "Rectangle.h" namespace shapes { Rectangle::Rectangle() { } Rectangle::Rectangle(int X0, int Y0, int X1, int Y1) { x0 = X0; y0 = Y0; x1 = X1; y1 = Y1; } Rectangle::~Rectangle() { } int Rectangle::getArea() { return (x1 - x0) * (y1 - y0); } }
My rect.pyx
# distutils: language = c++ # distutils: sources = Rectangle.cpp cdef extern from "Rectangle.h" namespace "shapes": cdef cppclass Rectangle: Rectangle() except + Rectangle(int, int, int, int) except + int x0, y0, x1, y1 int getArea() cdef class PyRectangle: cdef Rectangle c_rect def __cinit__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): return self.c_rect.getArea() cdef public int cythonfunc(PyRectangle py_rect): result = py_rect.get_area() return result
My main.cpp
#include <Python.h> #include "rect.h" #include "Rectangle.h" #include <iostream> int main (int argc, char *argv[]) { int result; Py_Initialize(); PyInit_rect(); shapes::Rectangle c_rect = shapes::Rectangle(0,0,2,1); result = cythonfunc(c_rect); std::cout<<result<<"\n"; Py_Finalize(); return 0; }
My Makefile
all: cython3 --cplus rect.pyx c++ -g -O2 -c rect.cpp -o rect.o `python3-config --includes` c++ -g -O2 -c Rectangle.cpp -o Rectangle.o `python3-config --includes` c++ -g -O2 -c main.cpp -o main.o `python3-config --includes` c++ -g -O2 -o rect Rectangle.o rect.o main.o `python3-config --libs` clean: rm -f rect rect.cpp rect.h *.o
My problem is with "cythonfunc" in rect.pyx. It is intended for a public function that can be called from main using a struct or object in the form of a rectangle as a parameter and returns the main.cpp area.
I tried c struct and python object, both do not work for me. If I use these codes, the compiler will throw an error
Error compiling Cython file: ------------------------------------------------------------ ... def __cinit__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): return self.c_rect.getArea() cdef public int cythonfunc(PyRectangle py_rect): ^ ------------------------------------------------------------ rect.pyx:19:27: Function declared public or api may not have private types
So, I added "public" to PyRectangle, but got another error:
Error compiling Cython file: ------------------------------------------------------------ ... Rectangle() except + Rectangle(int, int, int, int) except + int x0, y0, x1, y1 int getArea() cdef public class PyRectangle: ^ ------------------------------------------------------------ rect.pyx:12:5: Type object name specification required for 'public' C class
If I change cythonfunc to:
cdef public int cythonfunc(Rectangle c_rect): result = c_rect.getArea() return result
I got an error:
In file included from main.cpp:3:0: rect.h:21:42: warning: 'cythonfunc' initialized and declared 'extern' __PYX_EXTERN_C DL_IMPORT(int) cythonfunc(shapes::Rectangle); ^ rect.h:21:42: error: 'shapes' has not been declared main.cpp: In function 'int main(int, char**)': main.cpp:17:29: error: 'cythonfunc' cannot be used as a function result = cythonfunc(c_rect); ^
I can succeed only by passing individual x0, y0, x1, y1 as a parameter to cythonfunc. Is there a way to pass a cpp struct / object or python object as a parameter to a cython public function?