2012-10-23 20 views
8

Chcę udostępnić jedną z moich klas C++ jako moduł Pythona. Klasa jest zadeklarowana w nagłówku Foo.h i zaimplementowana w .cpp Foo.cpp. (g ++ - 4.5, Ubuntu x86_64). Jest to bardzo prosta klasa:Niezdefiniowany błąd symbolu podczas importowania modułu Cython

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

stworzyłem setup.py jak pokazano na Cython tutorialu:

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

a następnie zgodnie z instrukcją z samouczka Cython aby napisać moduł Foo.pyx Cython:

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) 

skompilować go za pomocą następującego polecenia: 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 

Teraz Foo.so obiekt biblioteki współdzielonej został utworzony, ale gdy chcę go zaimportować z Pythona, otrzymuję:

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

myślę że _ZN4FooD1Ev jest zniekształcone nazwisko konstruktora Foo ale nie rozumiem, jak brakuje symbolu.

Naprawdę nie mogę zrozumieć, jakiego symbolu brakuje w pliku obiektu udostępnionego. I po drugie, po komendzie python setup.py build_ext --inplace, mój plik jest zawiedli i zawiera wersję cytonizowaną.

Jak można zmienić nazwę zaniżonego pliku w innym formacie (na przykład .cxx) i uniknąć tego błędu linkera?

I potem zmodyfikował Foo.pyx w pFoo.pyx iw konsekwencji zmodyfikował setup.py, teraz po poleceniu setup mam cythonized wersję pFoo.pyx w Foo.cxx ale gdy próbuję zaimportować uzyskać

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

Co jest źle z moją konfiguracją i jak można rozwiązać moje problemy?

+0

Czy klasa Foo ma zdefiniowany konstruktor kopii w pliku cpp? –

+0

Nie, właściwie nie ma zdefiniowanego konstruktora kopiowania, kiedy zdefiniowano i zmieniono nazwę pliku 'Foo.pyx' w' pyFoo.pyx' rozwiązałem problem. – linello

Odpowiedz

2

Proponuję użyć innej nazwy dla twojego modułu cython, np.cFoo, aby uniknąć problemu nazwa Kolizja:

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

do zdefiniowania klasy C++, należy użyć słowa kluczowego „cppclass”, jak poniżej:

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

Powinieneś być w stanie uzyskać dostęp do klasy jak tak :

cdef Foo *foo = new Foo() 
foo.beta = 42 
Powiązane problemy