简体   繁体   中英

Undefined symbol error importing Cython module

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?

I suggest you use a different name for your cython module, eg cFoo, to avoid the name collision issue:

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize(
           "cFoo.pyx",                 # our Cython source
           sources=["Foo.cpp"],        # additional source file(s)
           language="c++",             # generate C++ code
      ))

To define a C++ class, use the 'cppclass' keyword, as below:

cdef extern from "Foo.h":
    cdef cppclass Foo:
        Foo()
        double alfa
        int beta

You should then be able to access your class like so:

cdef Foo *foo = new Foo()
foo.beta = 42

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM