Edit:
I've now tried the same code on a macbook and it works fine. So, the problem is confined to my Linux Mint 17.2 system with anaconda python 2.7, cython 0.23.4, and gcc 4.8. The macbook is using anaconda python 2.7, cython 0.22.1, and Apple LLVM version 6.1.0.
Original post:
I'm attempting to get the Cython c++ example working from here: http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html
As there is some room for interpretation, my exact code is pasted below. It's all in a single directory, cpp_example
. From within the cpp_example
directory, I compile using:
>python setup.py build_ext --inplace
Compilation prints the following output:
Compiling rect.pyx because it changed.
[1/1] Cythonizing rect.pyx
running build_ext
building 'rect' extension
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/jason/anaconda/envs/martian/include/python2.7 -c rect.cpp -o build/temp.linux-x86_64-2.7/rect.o
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++ [enabled by default]
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/jason/anaconda/envs/martian/include/python2.7 -c Rectangle.cpp -o build/temp.linux-x86_64-2.7/Rectangle.o
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++ [enabled by default]
g++ -pthread -shared -L/home/jason/anaconda/envs/martian/lib -Wl,-rpath=/home/jason/anaconda/envs/martian/lib,--no-as-needed build/temp.linux-x86_64-2.7/rect.o build/temp.linux-x86_64-2.7/Rectangle.o -L/home/jason/anaconda/envs/martian/lib -lpython2.7 -o build/lib.linux-x86_64-2.7/rect.so
Then I try to run:
>python main.py
And I get this error:
Traceback (most recent call last):
File "main.py", line 1, in <module>
import rect
ImportError: /home/jason/projects/martian/workspaces/workspace1/cpp_example/rect.so: undefined symbol: _ZN6shapes9Rectangle9getLengthEv
The undefined symbol looks like a mangled version of the getLength method of the Rectangle c++ class. I'm not sure if I'm doing something wrong or if there is a problem with the way my system is set up. Any suggestions of what might be going wrong would be greatly appreciated.
Code
Rectangle.cpp:
#include "Rectangle.h"
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;
}
}
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);
};
}
rect.pyx:
# distutils: sources = Rectangle.cpp
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 # hold a C++ instance which we're wrapping
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)
setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize(
"rect.pyx", # our Cython source
language="c++", # generate C++ code
))
main.py:
import rect
print rect.PyRectangle(1,1,2,2)