I am trying to learn how wrapping c++ code with cython works. In order to do this, I started with the basic c++ example on the cython webpage, found here: http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html
This looks simple enough, but I can't get it to work. Here is what I have done:
The Rectangle.h and Rectangle.cpp is copied directly from the web page
Rectangle.h:
namespace shapes {
class Rectangle {
public:
    int x0, y0, x1, y1;
    Rectangle(int x0, int y0, int x1, int y1);
    ~Rectangle();
    int getLength();
    int getHeight();
    int getArea();
    void move(int dx, int dy);
};
}
Rectangle.cpp
#include "Rectangle.h"
using namespace shapes;
Rectangle::Rectangle(int X0, int Y0, int X1, int Y1) {
    x0 = X0;
    y0 = Y0;
    x1 = X1;
    y1 = Y1;
}
Rectangle::~Rectangle() {
}
int Rectangle::getLength() {
    return (x1 - x0);
}
int Rectangle::getHeight()
{
    return (y1 - y0);
}
int Rectangle::getArea() {
    return (x1 - x0) * (y1 - y0);
}
void Rectangle::move(int dx, int dy) {
    x0 += dx;
    y0 += dy;
    x1 += dx;
    y1 += dy;
}
Then I create one .pyx file, called "rect.pyx" where I put the following code:
cdef extern from "Rectangle.h" namespace "shapes":
    cdef cppclass Rectangle:
        Rectangle(int, int, int, int) except +
        int x0, y0, x1, y1
        int getLength()
        int getHeight()
        int getArea()
        void move(int, int)
cdef class PyRectangle:
    cdef Rectangle *thisptr
    def __cinit__(self, int x0, int y0, int x1, int y1):
        self.thisptr = new Rectangle(x0, y0, x1, y1)
    def __dealloc__(self):
        del self.thisptr
    def getLength(self):
        return self.thisptr.getLength()
    def getHeight(self):
        return self.thisptr.getHeight()
    def getArea(self):
        return self.thisptr.getArea()
    def move(self, dx, dy):
        self.thisptr.move(dx, dy)
And finaly, one "setup.py" file:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize(
       "rect.pyx",                 # our Cython source
       sources=["Rectangle.cpp"],  # additional source file(s)
       language="c++",             # generate C++ code
  ))
I try to build the code by running the following command in the terminal on both ubuntu and mac osx (I get the same result on both operating systems):
python3 setup.py build_ext --inplace
This seems to compile fine, and a new .cpp file, plus a .so file appears in the folder, but when I start python and try to import the class I get the following error message:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: /home/codeFolder/rect.cpython-34m.so: undefined symbol: _ZN6shapes9Rectangle9getLengthEv
Whats wrong?
Look at your setup.py and the snippet in the link you used:
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules = cythonize(Extension(
           "rect",                                # the extesion name
           sources=["rect.pyx", "Rectangle.cpp"], # the Cython source and
                                                  # additional C++ source files
           language="c++",                        # generate and compile C++ code
      )))
Basically, you missed the call to Extension (further details in Extension and or cythoniza documentation ;) )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With