是否可以使用缓冲协议请求特定大小的缓冲区?

时间:2018-01-04 16:29:56

标签: python buffer cython

我试图了解如何使用缓冲协议,这里有一些代码可以将一大块Base64编码文本写入缓冲区:

cpdef object encode_base64(object fin, object fout):
    if not PyObject_CheckBuffer(fin):
        raise TypeError("fin must follow the buffer protocol")
    if not PyObject_CheckBuffer(fout):
        raise TypeError("fout must follow the buffer protocol")

    cdef Py_buffer in_view
    cdef int ret_code = PyObject_GetBuffer(fin, &in_view, PyBUF_SIMPLE)
    if ret_code < 0:
        return

    cdef Py_buffer out_view
    out_view.len = in_view.len;
    ret_code = PyObject_GetBuffer(fout, &out_view, PyBUF_SIMPLE)
    if ret_code < 0:
        return

    cdef size_t written;

    cdef bytes py_bytes = "1. out.buf: %s, out.len: %d\n".encode()
    cdef char* c_string = py_bytes
    printf(c_string, out_view.buf, out_view.len)

    cdef size_t used = encode_buffer(
        <unsigned char *>in_view.buf,
        in_view.len,
        <unsigned char *>out_view.buf,
        out_view.len,
        80,
        80,
        &written,
    )

    out_view.len = written;

    printf(c_string, out_view.buf, out_view.len)

    print "used: {}, written: {}, out: {}".format(used, written, printbuf(fout))

encode_buffer()在C代码中的其他地方定义如下:

size_t encode_buffer(
    const unsigned char* buf_in, const size_t buf_in_size,
    const unsigned char* buf_out, const size_t buf_out_size,
    const size_t pre_pad, const size_t padding, size_t* written);

它运作正常(至少在我的理解中)。

问题在于,如果我以这种方式在Python中使用此代码:

def test_printbuf():
    buf_in = BytesIO(b'1234567890')
    buf_in.seek(0)
    buf_out = BytesIO()
    buf_out.seek(0)
    encode_base64(buf_in.getbuffer(), buf_out.getbuffer())
    buf_out.seek(0)
    print('Encoded: {} -> {}'.format(buf_out.getbuffer(), buf_out.getvalue()))

buf_out似乎是空的。 (我可能会将编码后的文本写入一些我不应该触摸的记忆中,但这不是现在的主要问题。)

我的问题是:如何从BytesIO获取我想要的大小的缓冲区?由于它是使用空字符串初始化的,因此它具有零长度缓冲区,并且它忽略len结构的Py_buffer字段。

我查看了BytesIO的实现,它具有调整缓冲区大小的特殊功能,但它们特定于此对象,我希望我的代码是通用的。

0 个答案:

没有答案