2013-04-20 48 views
20

Tôi đang làm việc với thư viện C liên tục gọi một con trỏ hàm do người dùng cung cấp để nhận thêm dữ liệu. Tôi muốn viết một trình bao bọc Cython theo cách mà việc thực thi Python của cuộc gọi đó có thể trả về bất kỳ kiểu dữ liệu hợp lý nào như str, bytearray, các tệp ánh xạ bộ nhớ, v.v ... (cụ thể, hỗ trợ Buffer interface). những gì tôi có cho đến nay là:Sử dụng API bộ đệm trong Cython

from cpython.buffer cimport PyBUF_SIMPLE 
from cpython.buffer cimport Py_buffer 
from cpython.buffer cimport PyObject_GetBuffer 
from cpython.buffer cimport PyBuffer_Release 
from libc.string cimport memmove 

cdef class _callback: 
    cdef public object callback 
    cdef public object data 

cdef uint16_t GetDataCallback(void * userdata, 
           uint32_t wantlen, unsigned char * data, 
           uint32_t * gotlen): 

    cdef Py_buffer gotdata 
    box = <_callback> userdata 
    gotdata_object = box.callback(box.data, wantlen) 
    if not PyObject_CheckBuffer(gotdata_object): 
     # sulk 
     return 1 

    try: 
     PyObject_GetBuffer(gotdata_object, &gotdata, PyBUF_SIMPLE) 

     if not (0 < gotdata.len <= wantlen): 
      # sulk 
      return 1 

     memmove(data, gotdata.buf, gotdata.len) 

     return 0 
    finally: 
     PyBuffer_Release(&gotdata) 

Code tôi muốn viết sẽ tạo ra mã C tương đương, nhưng trông như thế này:

from somewhere cimport something 
from libc.string cimport memmove 

cdef class _callback: 
    cdef public object callback 
    cdef public object data 

cdef uint16_t GetDataCallback(void * userdata, 
           uint32_t wantlen, unsigned char * data, 
           uint32_t * gotlen): 


    cdef something gotdata 
    box = <_callback> userdata 
    gotdata = box.callback(box.data, wantlen) 
    if not (0 < gotdata.len <= wantlen): 
     # sulk 
     return 1 

    memmove(data, gotdata.buf, gotdata.len) 

    return 0 

Mã C tạo ra trông giống như những gì tôi nghĩ rằng nó nên làm; nhưng điều này có vẻ giống như việc đào bới xung quanh trong API Python một cách không cần thiết. Cython có cung cấp cú pháp đẹp hơn để đạt được hiệu ứng này không?

Trả lời

2

Nếu bạn muốn hỗ trợ mọi thứ thực hiện mọi biến thể của giao diện đệm kiểu mới hoặc kiểu cũ, thì bạn phải sử dụng API C.

Nhưng nếu bạn không quan tâm đến bộ đệm kiểu cũ, bạn hầu như luôn luôn có thể sử dụng một memoryview:

Cython memoryviews hỗ trợ gần như tất cả đối tượng xuất khẩu giao diện của Python đệm phong cách mới. Đây là giao diện đệm được mô tả trong PEP 3118. Các mảng NumPy hỗ trợ giao diện này, cũng như các mảng Cython. "Gần như tất cả" là vì giao diện bộ đệm Python cho phép các phần tử trong mảng dữ liệu tự trở thành con trỏ; Bộ nhớ cache của Cython chưa hỗ trợ tính năng này.

Điều này tất nhiên bao gồm str (hoặc, trong 3.x, bytes), bytearray, vv-nếu bạn làm theo các liên kết, bạn có thể nhận thấy rằng nó liên kết đến cùng một trang để giải thích những gì nó hỗ trợ mà bạn liên kết để giải thích những gì bạn muốn hỗ trợ.

Đối với mảng 1D của các nhân vật (như str), đó là:

cdef char [:] gotdata 
Các vấn đề liên quan