Author: Ronan Lamy <ronan.l...@gmail.com> Branch: buffer-cleanup Changeset: r89988:6f7a4aa078bd Date: 2017-02-07 03:08 +0000 http://bitbucket.org/pypy/pypy/changeset/6f7a4aa078bd/
Log: Test and fix for the fields of the Py_buffer not being set correctly in our bf_getbuffer diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py --- a/pypy/module/cpyext/buffer.py +++ b/pypy/module/cpyext/buffer.py @@ -1,10 +1,10 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import ( - cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP, + cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP, cts, generic_cpy_call, PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES, PyBUF_SIMPLE) -from pypy.module.cpyext.pyobject import PyObject, Py_IncRef, Py_DecRef +from pypy.module.cpyext.pyobject import PyObject, incref, Py_DecRef @cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1) def PyObject_AsCharBuffer(space, obj, bufferp, sizep): @@ -35,6 +35,33 @@ Py_DecRef(space, view.c_obj) return 0 +def fill_buffer(space, view, pybuf, py_obj): + view.c_buf = cts.cast('void *', pybuf.get_raw_address()) + view.c_obj = py_obj + if py_obj: + incref(space, py_obj) + view.c_len = pybuf.getlength() + view.c_itemsize = pybuf.getitemsize() + rffi.setintfield(view, 'c_readonly', int(pybuf.readonly)) + rffi.setintfield(view, 'c_ndim', pybuf.getndim()) + view.c_format = rffi.str2charp(pybuf.getformat()) + shape = pybuf.getshape() + if not shape: + view.c_shape = lltype.nullptr(Py_ssize_tP.TO) + else: + view.c_shape = cts.cast('Py_ssize_t*', view.c__shape) + for i, n in enumerate(shape): + view.c_shape[i] = n + strides = pybuf.getstrides() + if not strides: + view.c_strides = lltype.nullptr(Py_ssize_tP.TO) + else: + view.c_strides = cts.cast('Py_ssize_t*', view.c__strides) + for i, n in enumerate(strides): + view.c_strides[i] = n + view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) + view.c_internal = lltype.nullptr(rffi.VOIDP.TO) + @cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t, lltype.Signed, lltype.Signed], rffi.INT, error=-1) @@ -51,7 +78,7 @@ view.c_len = length view.c_obj = obj if obj: - Py_IncRef(space, obj) + incref(space, obj) view.c_itemsize = 1 rffi.setintfield(view, 'c_readonly', readonly) rffi.setintfield(view, 'c_ndim', 1) diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c --- a/pypy/module/cpyext/test/array.c +++ b/pypy/module/cpyext/test/array.c @@ -2871,7 +2871,17 @@ return PyBytes_FromStringAndSize((char*)ptr, size); } - +static PyObject * +write_buffer_len(PyObject * self, PyObject * obj) +{ + void* buf; + Py_ssize_t buf_len; + if (PyObject_AsWriteBuffer(obj, &buf, &buf_len) < 0) { + PyErr_SetString(PyExc_ValueError, "bad value"); + return NULL; + } + return PyLong_FromLong(buf_len); +} /*********************** Install Module **************************/ @@ -2880,6 +2890,7 @@ PyDoc_STR("Internal. Used for pickling support.")}, {"switch_multiply", (PyCFunction)switch_multiply, METH_NOARGS, NULL}, {"readbuffer_as_string", (PyCFunction)readbuffer_as_string, METH_VARARGS, NULL}, + {"write_buffer_len", write_buffer_len, METH_O, NULL}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py --- a/pypy/module/cpyext/test/test_arraymodule.py +++ b/pypy/module/cpyext/test/test_arraymodule.py @@ -84,6 +84,9 @@ arr = module.array('u', '123') view = memoryview(arr) assert view.itemsize == 4 + assert module.write_buffer_len(arr) == 12 + assert len(module.readbuffer_as_string(arr)) == 12 + assert len(module.readbuffer_as_string(view)) == 12 def test_subclass(self): import struct diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -555,11 +555,10 @@ @slot_function([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real], rffi.INT_real, error=-1) def bf_getbuffer(space, w_obj, view, flags): - from pypy.module.cpyext.buffer import PyBuffer_FillInfo + from pypy.module.cpyext.buffer import fill_buffer buf = space.buffer_w(w_obj, rffi.cast(lltype.Signed, flags)) - c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) - return PyBuffer_FillInfo(space, view, w_obj, c_buf, - space.len_w(w_obj), 0, flags) + fill_buffer(space, view, buf, as_pyobj(space, w_obj)) + return 0 def setup_buffer_procs(space, w_type, pto): bufspec = w_type.layout.typedef.buffer _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit