How to create a public cython function that can receive c++ struct/instance or python object as parameter? -
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 "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 related "cythonfunc" in rect.pyx. intended public function can called main rectangle struct/object parameter, , return area main.cpp.
i've tried c struct , python object, both not work me. if use codes, compiler gives error of
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 added "public" pyrectangle, got 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 'public' c class
if change cythonfunc to:
cdef public int cythonfunc(rectangle c_rect): result = c_rect.getarea() return result
i got error of:
in file included main.cpp:3:0: rect.h:21:42: warning: ‘cythonfunc’ initialized , 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 used function result = cythonfunc(c_rect); ^
i can success passing separate x0, y0, x1, y1 parameter cythonfunc. there correct way passing cpp struct/object or python object parameter cython public function?
with respect second attempt (which more sensible way of calling c++, although i'd pass reference):
cdef public int cythonfunc(rectangle c_rect): result = c_rect.getarea() return result
the issue doesn't know rectangle
is, since cython generated rect.h
doesn't include rectangle.h
. easiest way fix swap order of includes in main.cpp
:
#include "rectangle.h" // 1 first #include "rect.h"
the error "shapes has not been declared" telling this...
with respect first attempt, right have make pyrectangle
public. need specify "type object name" cython tells you. shown here (although isn't hugely clear...):
cdef public class pyrectangle [object c_pyrect, type c_pyrect_t]: # ... before
this ensures pyrectangle available c/c++ struct c_pyrect
(and cythonfunc
signature int cythonfunc(struct c_pyrect *);
.)
also, python typeobject
defining pyrectangle
available c_pyrect_t
, don't need that.
Comments
Post a Comment