2012-10-23 7 views
8

Ich möchte eine meiner C++ - Klassen als Python-Modul zur Verfügung stellen. Die Klasse wird in einem Header Foo.h deklariert und in einer .cpp Foo.cpp implementiert. (g ++ - 4.5, Ubuntu x86_64). Es ist ein sehr, sehr einfache Klasse:Undefined Symbol Fehler beim Importieren von Cython-Modul

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; 
}; 

habe ich eine setup.py wie in Cython Tutorial gezeigt:

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}, 
) 

und folgte der Anweisung des cython Tutorial mein Foo.pyx cython Modul zu schreiben:

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) 

ich es mit dem folgenden Befehl kompilieren: 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 

Nun ist die Foo.so Shared Library-Objekt wird erstellt, aber wenn ich es aus Python importieren möchte, bekomme ich:

>>> import Foo 
     Traceback (most recent call last): 
     File "<stdin>", line 1, in <module> 
     ImportError: ./Foo.so: undefined symbol: _ZN4FooD1Ev 
>>> 

Ich denke, dass _ZN4FooD1Ev der verstümmelten Name des Konstrukteurs von Foo ist aber nicht verstehen, wie das Symbol fehlt.

Ich kann wirklich nicht verstehen, welches Symbol aus der gemeinsamen Objektdatei fehlt. Und als zweiter Punkt, nach dem python setup.py build_ext --inplace Befehl, meine Foo.cpp Datei ist vermasselt und enthält die Cythonized-Version.

Wie ist es möglich, die cythonisierte Datei in einem anderen Format (zum Beispiel .cxx) umzubenennen und diesen Linkerfehler zu vermeiden?

I modifiziert dann die Foo.pyx in pFoo.pyx und verändert damit die setup.py, jetzt nach dem Setup-Befehl ich die cythonized Version von pFoo.pyx in Foo.cxx haben, aber wenn ich versuche ich die

ImportError: dynamic module does not define init function (initpyFoo)

erhalten zu importieren Was ist falsch mit meinem Setup und wie ist es möglich, meine Probleme zu lösen?

+0

Ist der Kopierkonstruktor der Foo-Klasse in der cpp-Datei definiert? –

+0

Nein, es hat eigentlich keinen Kopierkonstruktor definiert, als ich den Namen 'Foo.pyx' in' pyFoo.pyx' definiert und umbenannt habe, habe ich das Problem gelöst. – linello

Antwort

2

Ich schlage vor, dass Sie einen anderen Namen für Ihr Cython-Modul, z.cFoo, den Namen Kollision Problem zu vermeiden:

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 
    )) 

eine C++ Klasse zu definieren, verwenden Sie das Schlüsselwort ‚cppclass‘, wie unten:

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

Sie sollten dann in der Lage sein, Ihre Klasse zugreifen wie so :

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