2012-10-23 24 views
8

C++ sınıflarımdan birini Python modülü olarak kullanıma sunmak istiyorum. Sınıf bir Foo.h numaralı başlıkta bildirilmiş ve bir .cpp Foo.cpp'da uygulanmıştır. (g ++ - 4.5, Ubuntu x86_64).Cython modülünü içe aktarma tanımsız sembol hatası

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}, 
) 
0: Cython öğretici gösterildiği gibi
class Foo 
{ 
public: 

    Foo() 
    Foo(const Foo& orig); 
    ~Foo(); 
    double alfa; 
    int beta; 
}; 

Ben setup.py yarattı:

Foo.cpp:

Foo::Foo() : alfa(1.0), beta(1) 
{ 

} 

Foo::~Foo() 
{ 
} 

Foo.h Bu çok çok basit sınıf var Aşağıdaki komutu kullanarak derlemek

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) 

: Şimdi 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 

ve benim Foo.pyx Cython modülünü yazmak için Cython öğretici talimat takip Paylaşılan kütüphane nesnesi oluşturuldu ancak python'dan içe aktarmak istediğimde:

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

Ben _ZN4FooD1EvFoo yapıcısı mangled adıdır ancak sembolü eksik anlamıyorum düşünüyorum.

Paylaşılan nesne dosyasında hangi sembolün eksik olduğunu gerçekten anlayamıyorum. Ve python setup.py build_ext --inplace komutundan sonra, Foo.cpp dosyam dosya mesajlaşır ve cythonized sürümü içerir.

Sönümlendirilmiş dosyayı başka bir biçimde (örneğin, .cxx) yeniden adlandırmak ve bu bağlantı hatalarından kaçınmak nasıl mümkündür?

Sonra pFoo.pyx içinde Foo.pyx modifiye ve sonuç setup.py şimdi kurmak komutundan sonra ben Foo.cxx içinde pFoo.pyx arasında cythonized sürümüne sahip değiştirilmiş ama içe denediğimde

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

olsun ne benim kurulumumda yanlış ve sorunlarımı çözmek nasıl mümkün olabilir?

+0

Foo sınıfının cpp dosyasında tanımlanmış kopya kurucusu var mı? –

+0

Hayır, aslında tanımlanmış bir kopya kurucusu yok, 'pyo.pyx' adında 'Foo.pyx' adı tanımlandığında ve yeniden adlandırıldığında sorunu çözdüm. – linello

cevap

2

Cython modülünüz için farklı bir ad kullanmanızı öneririm, örn.

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

Sonra şöyle sınıfınızı erişmek mümkün olmalıdır: aşağıdaki gibi 'cppclass' anahtar kelimesini kullanıyorum

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

bir C++ sınıfı tanımlamak için: cFoo, adı çarpışma sorunu önlemek için :

cdef Foo *foo = new Foo() 
foo.beta = 42 
İlgili konular