2012-10-23 13 views
8

Desidero rendere disponibile una delle mie classi C++ come modulo Python. La classe è dichiarata nell'intestazione Foo.h e implementata in un file .cpp Foo.cpp. (g ++ - 4.5, Ubuntu x86_64). Si tratta di una classe molto molto semplice:Errore di simbolo non definito importazione del modulo 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; 
}; 

ho creato un setup.py come mostrato nella 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}, 
) 

e seguito le istruzioni del tutorial Cython di scrivere il mio modulo 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) 

compilo con il seguente comando: 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 

Ora il Foo.so l'oggetto libreria condivisa viene creato ma quando voglio importarlo da python, ottengo:

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

penso che _ZN4FooD1Ev è il nome storpiato del costruttore di Foo, ma non capisco come manca il simbolo.

Non riesco davvero a capire quale simbolo manca nel file oggetto condiviso. E come secondo punto, dopo il comando python setup.py build_ext --inplace, il mio file Foo.cpp è incasinato e contiene la versione cythonized.

Come è possibile rinominare il file cythonizzato in un altro formato (ad esempio .cxx) ed evitare l'errore del linker?

Ho poi modificato il Foo.pyx in pFoo.pyx e conseguentemente modificato la setup.py, ora, dopo il comando setup Ho la versione cythonized di pFoo.pyx in Foo.cxx ma quando si tenta di importare ho la

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

Cosa è sbagliato con il mio setup e come è possibile risolvere i miei problemi?

+0

La classe Foo ha il suo costruttore di copia definito nel file cpp? –

+0

No, in realtà non è stato definito alcun costruttore di copia, quando definito e rinominato il nome di 'Foo.pyx' in' pyFoo.pyx' ho risolto il problema. – linello

risposta

2

Suggerisco di utilizzare un nome diverso per il modulo cython, ad es.CFoo, per evitare la questione del nome di collisione:

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

per definire una classe C++, utilizzare la parola chiave 'cppclass', come di seguito:

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

Si dovrebbe quindi essere in grado di accedere la classe in questo modo :

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