I want to make available one of my c++ classes as Python module. The class is declared in a header Foo.h and implemented in a .cpp Foo.cpp.
(g++-4.5, Ubuntu x86_64). It's a very very simple class:
Foo.cpp:
Foo::Foo() : alfa(1.0), beta(1)
{
}
Foo::~Foo()
{
}
Foo.h:
class Foo
{
public:
Foo()
Foo(const Foo& orig);
~Foo();
double alfa;
int beta;
};
I created a setup.py as shown in Cython tutorial:
setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
name = 'MyDemo',
ext_modules=[
Extension("Foo"
sources=["Foo.pyx"],
include_dirs=[".","../eigen/"],
language="c++"),
],
cmdclass = {'build_ext': build_ext},
)
and followed the instruction of the cython tutorial to write my Foo.pyx cython module:
Foo.pyx
cdef extern from "Foo.h":
ctypedef struct c_Foo "Foo":
double alfa
c_Foo *new_Foo "new Foo" ()
void del_Foo "delete" (c_Foo *myfoo)
cdef class Foo:
cdef c_Foo *thisptr # hold a C++ instance which we're wrapping
def __cinit__(self):
self.thisptr = new_Foo()
def __dealloc__(self):
del_Foo(self.thisptr)
I compile it with the following command:
python setup.py build_ext --inplace
running build_ext
skipping 'Foo.cpp' Cython extension (up-to-date)
building 'Foo extension
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I. -I../eigen/ -I/usr/include/python2.6 -c Foo.cpp -o build/temp.linux-x86_64-2.6/Foo.o
cc1plus: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux-x86_64-2.6/Foo.o -o /home/linello/prova/Foo.so
Now the Foo.so shared library object is created but when I want to import it from python, I get:
>>> import Foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: ./Foo.so: undefined symbol: _ZN4FooD1Ev
>>>
I think that _ZN4FooD1Ev is the mangled name of the constructor of Foo but don't understand how is missing the symbol.
I really can't understand what symbol is missing from the shared object file.
And as second point, after the python setup.py build_ext --inplace command, my Foo.cpp file is messed up and contains the cythonized version.
How is possible to rename the cythonized file in another format (for example .cxx) and avoid that linker error?
I then modified the Foo.pyx in pFoo.pyx and consequently modified the setup.py, now after the setup command I have the cythonized version of pFoo.pyx in Foo.cxx but when I try to import I get the
ImportError: dynamic module does not define init function (initpyFoo)
What is wrong with my setup and how is possible to solve my problems?