2012-08-30 24 views
19
cdef extern from "Foo.h": 
    cdef cppclass Bar: 
     pass 

cdef class PyClass: 
    cdef Bar *bar 

    def __cinit__(self, Bar *b) 
     bar = b 

này sẽ luôn luôn cho tôi một cái gì đó như:
Cannot convert Python object argument to type 'Bar *'Passing C++ con trỏ như là đối số vào Cython chức năng

Có cách nào để thực hiện điều này, hay tôi cần phải giải nén tất cả mọi thứ từ một đối tượng Bar, tạo tương đương Python, chuyển nó vào, sau đó tạo lại nó trong PyClass?

Trả lời

5

Đối với mỗi lớp CDEF tạo một hàm CDEF toàn cầu hoạt động như một nhà xây dựng, CefResponse là một đối tượng C++, PyResponse một tương đương trăn của một C++ đối tượng:

cdef object CreatePyResponse(CefRefPtr[CefResponse] cefResponse): 

    pyResponse = PyResponse() 
    pyResponse.cefResponse = cefResponse 
    return pyResponse 

cdef class PyResponse: 

    cdef CefRefPtr[CefResponse] cefResponse 

    def GetStatus(self): 

     return (<CefResponse*>(self.cefResponse.get())).GetStatus() 

Vì vậy, thay vì resp = PyResponse(cppObject) gọi resp = CreatePyResponse(cppObject).

Ví dụ lấy từ CEF Python: https://code.google.com/p/cefpython/source/browse/cefpython/response.pyx?r=0250b65e046a

2

lớp Python chấp nhận lập luận Python. Để vượt qua một C++ luận bạn cần phải quấn nó:

# distutils: language = c++ 

cdef extern from "Foo.h" namespace "baz": 
    cdef cppclass Bar: 
     Bar(double d) 
     double get() 

cdef class PyBar: # wrap Bar class 
    cdef Bar *thisptr 
    def __cinit__(self, double d): 
     self.thisptr = new Bar(d) 
    def __dealloc__(self): 
     del self.thisptr 
    property d: 
     def __get__(self): 
      return self.thisptr.get() 

PyBar trường hợp có thể được sử dụng như bất kỳ Python khác các đối tượng cả từ Cython và Python tinh khiết:

class PyClass: 
    def __init__(self, PyBar bar): 
     self.bar = bar 

print(PyClass(PyBar(1)).bar.d) 
9

Tôi đã xem qua vấn đề này cố gắng để quấn Mã C với cấu trúc như các lớp python. Vấn đề có vẻ là chức năng "đặc biệt" bao gồm __init____cinit__ phải được khai báo là def thay vì cdef. Điều này có nghĩa là chúng có thể được gọi từ python bình thường, vì vậy các tham số kiểu được bỏ qua một cách hiệu quả và mọi thứ được coi là đối tượng.

Trong J.F. Câu trả lời của Sebastian sửa chữa không phải là gói - một đôi là một kiểu số cơ bản và do đó có một chuyển đổi mặc định giữa loại C/C++ và đối tượng Python. Câu trả lời của Czarek về cơ bản là chính xác - bạn cần phải sử dụng một thành ngữ hàm tạo giả, sử dụng một hàm toàn cầu. Không thể sử dụng trình trang trí @staticmethod vì chúng không thể được áp dụng cho các hàm cdef. Câu trả lời trông đơn giản hơn trên ví dụ ban đầu được cung cấp.

cdef extern from "Foo.h": 
    cdef cppclass Bar: 
     pass 

cdef class PyClass: 
    cdef Bar *bar 

cdef PyClass_Init(Bar *b): 
    result = PyClass() 
    result.bar = b 
    return result 
+3

Trên phiên bản Cython gần đây nhất có thể được áp dụng cho các chức năng cdef. vào một lớp tĩnh cho một tổ chức neater. – Dologan

+0

Lớp 'Bar' C++ không phải là loại số cơ bản và không có chuyển đổi mặc định. – jfs

+0

@ J.F.Sebastian Bạn có thể giải thích ý của bạn không? Thanh không phải là một kiểu số cơ bản để lưu trữ một con trỏ đến nó. – Amoss

6

Tính đến Cython 0.21 nó đã có thể tuyên bố cdef phương pháp với @staticmethod trang trí. Điều này cho phép các phương thức tạo tĩnh có tham số không phải Python:

cdef extern from "Foo.h": 
    cdef cppclass Bar: 
     pass 

cdef class PyClass: 
    cdef Bar *bar 

    @staticmethod 
    cdef create(Bar *bar): 
     cdef PyClass pc = PyClass() 
     pc.bar = bar 
     return pc 
Các vấn đề liên quan