[pypy-commit] pypy buffer-interface: PyMemoryView_GET_BUFFER wip, len(memorview()) is prod(shape), but getlength() is number of bytes
mattip
pypy.commits at gmail.com
Sun Aug 28 19:48:38 EDT 2016
Author: Matti Picus <matti.picus at gmail.com>
Branch: buffer-interface
Changeset: r86668:3ec8f09e764d
Date: 2016-08-29 09:24 +1000
http://bitbucket.org/pypy/pypy/changeset/3ec8f09e764d/
Log: PyMemoryView_GET_BUFFER wip, len(memorview()) is prod(shape), but
getlength() is number of bytes
diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -1,7 +1,8 @@
from pypy.module.cpyext.api import (cpython_api, Py_buffer, CANNOT_FAIL,
- build_type_checkers)
-from pypy.module.cpyext.pyobject import PyObject
-from rpython.rtyper.lltypesystem import lltype
+ build_type_checkers, Py_ssize_tP)
+from pypy.module.cpyext.pyobject import PyObject, as_pyobj, incref
+from rpython.rtyper.lltypesystem import lltype, rffi
+from pypy.objspace.std.memoryobject import W_MemoryView
PyMemoryView_Check, PyMemoryView_CheckExact = build_type_checkers("MemoryView", "w_memoryview")
@@ -20,21 +21,29 @@
object. The object must be a memoryview instance; this macro doesn't
check its type, you must do it yourself or you will risk crashes."""
view = lltype.malloc(Py_buffer, flavor='raw', zero=True)
- # TODO - fill in fields
- '''
- view.c_buf = buf
- view.c_len = length
- view.c_obj = obj
- Py_IncRef(space, obj)
- view.c_itemsize = 1
- rffi.setintfield(view, 'c_readonly', readonly)
- rffi.setintfield(view, 'c_ndim', 0)
- view.c_format = lltype.nullptr(rffi.CCHARP.TO)
- view.c_shape = lltype.nullptr(Py_ssize_tP.TO)
- view.c_strides = lltype.nullptr(Py_ssize_tP.TO)
+ if not isinstance(w_obj, W_MemoryView):
+ return view
+ try:
+ view.c_buf = rffi.cast(rffi.VOIDP, w_obj.buf.get_raw_address())
+ except ValueError:
+ return view
+ view.c_len = w_obj.getlength()
+ view.c_obj = as_pyobj(space, w_obj)
+ incref(space, view.c_obj)
+ view.c_itemsize = w_obj.buf.getitemsize()
+ rffi.setintfield(view, 'c_readonly', w_obj.buf.readonly)
+ ndim = w_obj.buf.getndim()
+ rffi.setintfield(view, 'c_ndim', ndim)
+ view.c_format = rffi.str2charp(w_obj.buf.getformat())
+ view.c_shape = lltype.malloc(Py_ssize_tP.TO, ndim, flavor='raw')
+ view.c_strides = lltype.malloc(Py_ssize_tP.TO, ndim, flavor='raw')
+ shape = w_obj.buf.getshape()
+ strides = w_obj.buf.getstrides()
+ for i in range(ndim):
+ view.c_shape[i] = shape[i]
+ view.c_strides[i] = strides[i]
view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO)
view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
- '''
return view
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -508,10 +508,9 @@
@cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL)
def PyBuffer_Release(space, view):
"""
- Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
-
- This is not a complete re-implementation of the CPython API; it only
- provides a subset of CPython's behavior.
+ Release the buffer view. This should be called when the buffer is
+ no longer being used as it may free memory from it
"""
Py_DecRef(space, view.c_obj)
view.c_obj = lltype.nullptr(PyObject.TO)
+ # XXX do other fields leak memory?
diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py
--- a/pypy/module/cpyext/test/test_memoryobject.py
+++ b/pypy/module/cpyext/test/test_memoryobject.py
@@ -21,6 +21,7 @@
y = memoryview(arr)
assert y.format == 'i'
assert y.shape == (10,)
+ assert len(y) == 10
s = y[3]
assert len(s) == struct.calcsize('i')
assert s == struct.pack('i', 3)
diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -115,7 +115,7 @@
self.buf.setslice(start, value.as_str())
def descr_len(self, space):
- return space.wrap(self.buf.getlength())
+ return space.wrap(self.buf.getlength() / self.buf.getitemsize())
def w_get_format(self, space):
return space.wrap(self.buf.getformat())
More information about the pypy-commit
mailing list