2012-10-23 24 views
8

Tôi muốn tạo sẵn một trong các lớp C++ của tôi làm mô-đun Python. Lớp được khai báo trong tiêu đề Foo.h và được triển khai trong một .cpp Foo.cpp. (g ++ - 4.5, Ubuntu x86_64). Đó là một lớp rất rất đơn giản:Lỗi biểu tượng không xác định nhập khẩu mô-đun 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; 
}; 

Tôi tạo ra một setup.py như trong Cython hướng dẫn:

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

và theo chỉ dẫn của hướng dẫn cython để viết mô-đun Foo.pyx cython tôi:

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) 

tôi biên dịch nó với lệnh sau: 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 

Bây giờ Foo.so đối tượng thư viện được chia sẻ được tạo nhưng khi tôi muốn nhập nó từ python, tôi nhận được:

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

Tôi nghĩ rằng _ZN4FooD1Ev là tên đọc sai của các nhà xây dựng của Foo nhưng không hiểu làm thế nào là mất tích biểu tượng.

Tôi thực sự không thể hiểu biểu tượng nào bị thiếu trong tệp đối tượng được chia sẻ. Và là điểm thứ hai, sau lệnh python setup.py build_ext --inplace, tệp Foo.cpp của tôi là bị lỗi và chứa phiên bản được mã hoá.

Làm cách nào để đổi tên tệp được mã hóa ở định dạng khác (ví dụ: .cxx) và tránh lỗi liên kết đó?

sau đó tôi sửa đổi Foo.pyx trong pFoo.pyx và do sửa đổi setup.py, bây giờ sau khi lệnh thiết lập tôi có phiên bản cythonized của pFoo.pyx trong Foo.cxx nhưng khi tôi cố gắng nhập tôi nhận được

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

gì là sai với thiết lập của tôi và làm thế nào có thể để giải quyết vấn đề của tôi?

+0

Lớp Foo có trình tạo bản sao được xác định trong tệp cpp không? –

+0

Không, nó thực sự không có hàm tạo bản sao nào được xác định, khi được định nghĩa và đổi tên thành 'Foo.pyx' trong' pyFoo.pyx' tôi đã giải quyết được vấn đề. – linello

Trả lời

2

Tôi khuyên bạn nên sử dụng tên khác cho mô-đun cython của mình, ví dụ:cFoo, để tránh những vấn đề va chạm tên:

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

Để xác định một ++ lớp C, sử dụng từ khóa 'cppclass', như sau:

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

Sau đó, bạn sẽ có thể truy cập vào lớp học của bạn như vậy :

cdef Foo *foo = new Foo() 
foo.beta = 42 
Các vấn đề liên quan