Author: Matti Picus <[email protected]>
Branch: issue2444
Changeset: r89189:75e80dab0448
Date: 2016-12-19 20:27 +0200
http://bitbucket.org/pypy/pypy/changeset/75e80dab0448/
Log: create PyMemoryViewObject with a Py_buffer view, change Py_buffer ->
rffi.CStruct
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -630,25 +630,27 @@
PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
PyVarObject = lltype.Ptr(PyVarObjectStruct)
-Py_buffer = cpython_struct(
- "Py_buffer", (
+Py_buffer = rffi.CStruct( "Py_buffer",
('buf', rffi.VOIDP),
('obj', PyObject),
('len', Py_ssize_t),
('itemsize', Py_ssize_t),
- ('readonly', lltype.Signed),
- ('ndim', lltype.Signed),
+ ('readonly', rffi.INT_real),
+ ('ndim', rffi.INT_real),
('format', rffi.CCHARP),
('shape', Py_ssize_tP),
('strides', Py_ssize_tP),
+ ('suboffsets', Py_ssize_tP),
('_format', rffi.CFixedArray(rffi.UCHAR, Py_MAX_FMT)),
('_shape', rffi.CFixedArray(Py_ssize_t, Py_MAX_NDIMS)),
('_strides', rffi.CFixedArray(Py_ssize_t, Py_MAX_NDIMS)),
- ('suboffsets', Py_ssize_tP),
#('smalltable', rffi.CFixedArray(Py_ssize_t, 2)),
- ('internal', rffi.VOIDP)
- ))
+ ('internal', rffi.VOIDP),
+ hints={'size': 6 * rffi.sizeof(Py_ssize_tP) + 2 *
rffi.sizeof(Py_ssize_t) +
+ 2 * rffi.sizeof(rffi.INT_real) +
rffi.sizeof(rffi.CCHARP) +
+ Py_MAX_FMT * rffi.sizeof(rffi.UCHAR) +
+ 2 * Py_MAX_NDIMS * rffi.sizeof(Py_ssize_t)})
Py_bufferP = lltype.Ptr(Py_buffer)
@specialize.memo()
diff --git a/pypy/module/cpyext/classobject.py
b/pypy/module/cpyext/classobject.py
--- a/pypy/module/cpyext/classobject.py
+++ b/pypy/module/cpyext/classobject.py
@@ -1,7 +1,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
PyObjectFields, CANNOT_FAIL,
- cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
+ cpython_api, bootstrap_function, build_type_checkers)
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref,
Py_DecRef, make_typedescr
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.module.__builtin__.interp_classobj import W_ClassObject,
W_InstanceObject
diff --git a/pypy/module/cpyext/include/memoryobject.h
b/pypy/module/cpyext/include/memoryobject.h
--- a/pypy/module/cpyext/include/memoryobject.h
+++ b/pypy/module/cpyext/include/memoryobject.h
@@ -5,6 +5,14 @@
extern "C" {
#endif
+/* The struct is declared here but it shouldn't
+ be considered public. Don't access those fields directly,
+ use the functions instead! */
+typedef struct {
+ PyObject_HEAD
+ Py_buffer view;
+} PyMemoryViewObject;
+
diff --git a/pypy/module/cpyext/include/object.h
b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -145,7 +145,7 @@
/* Py3k buffer interface, adapted for PyPy */
#define Py_MAX_NDIMS 32
#define Py_MAX_FMT 128
-typedef struct bufferinfo {
+typedef struct Py_buffer {
void *buf;
PyObject *obj; /* owned reference */
Py_ssize_t len;
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,14 +1,57 @@
from pypy.module.cpyext.api import (cpython_api, Py_buffer, CANNOT_FAIL,
- Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers,
Py_ssize_tP)
-from pypy.module.cpyext.pyobject import PyObject, make_ref, incref, from_ref
+ Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers,
+ Py_ssize_tP, PyObjectFields, cpython_struct,
+ bootstrap_function, Py_bufferP)
+from pypy.module.cpyext.pyobject import (PyObject, make_ref, as_pyobj, incref,
+ decref, from_ref, make_typedescr)
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.rarithmetic import widen
from pypy.objspace.std.memoryobject import W_MemoryView
+from pypy.module.cpyext.object import _dealloc
from pypy.module.cpyext.import_ import PyImport_Import
-PyMemoryView_Check, PyMemoryView_CheckExact =
build_type_checkers("MemoryView", "w_memoryview")
+PyMemoryView_Check, PyMemoryView_CheckExact = build_type_checkers("MemoryView")
-@cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real],
+
+PyMemoryViewObjectStruct = lltype.ForwardReference()
+PyMemoryViewObject = lltype.Ptr(PyMemoryViewObjectStruct)
+PyMemoryViewObjectFields = PyObjectFields + \
+ (("view", Py_buffer),)
+cpython_struct("PyMemoryViewObject", PyMemoryViewObjectFields,
PyMemoryViewObjectStruct)
+
+@bootstrap_function
+def init_memoryobject(space):
+ "Type description of PyDictObject"
+ make_typedescr(W_MemoryView.typedef,
+ basestruct=PyMemoryViewObject.TO,
+ attach=memory_attach,
+ dealloc=memory_dealloc,
+ #realize=memory_realize,
+ )
+
+def memory_attach(space, py_obj, w_obj, w_userdata=None):
+ """
+ Fills a newly allocated PyMemoryViewObject with the given W_MemoryView
object.
+ """
+ py_obj = rffi.cast(PyMemoryViewObject, py_obj)
+ py_obj.c_view.c_obj = rffi.cast(PyObject, 0)
+
+def memory_realize(space, py_obj):
+ """
+ Creates the memory object in the interpreter
+ """
+ raise oefmt(space.w_NotImplementedError, "cannot call this yet")
+
+@cpython_api([PyObject], lltype.Void, header=None)
+def memory_dealloc(space, py_obj):
+ mem_obj = rffi.cast(PyMemoryViewObject, py_obj)
+ if mem_obj.c_view.c_obj:
+ decref(space, mem_obj.c_view.c_obj)
+ mem_obj.c_view.c_obj = rffi.cast(PyObject, 0)
+ _dealloc(space, py_obj)
+
+
+@cpython_api([PyObject, Py_bufferP, rffi.INT_real],
rffi.INT_real, error=-1)
def PyObject_GetBuffer(space, w_obj, view, flags):
"""Export obj into a Py_buffer, view. These arguments must
@@ -111,7 +154,7 @@
sd *= dim
return 1
-@cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real,
error=CANNOT_FAIL)
+@cpython_api([Py_bufferP, lltype.Char], rffi.INT_real, error=CANNOT_FAIL)
def PyBuffer_IsContiguous(space, view, fort):
"""Return 1 if the memory defined by the view is C-style (fort is
'C') or Fortran-style (fort is 'F') contiguous or either one
@@ -132,7 +175,7 @@
def PyMemoryView_FromObject(space, w_obj):
return space.call_method(space.builtin, "memoryview", w_obj)
-@cpython_api([lltype.Ptr(Py_buffer)], PyObject)
+@cpython_api([Py_bufferP], PyObject)
def PyMemoryView_FromBuffer(space, view):
"""Create a memoryview object wrapping the given buffer-info structure
view.
The memoryview object then owns the buffer, which means you shouldn't
@@ -149,14 +192,15 @@
# XXX needed for numpy on py3k
raise NotImplementedError('PyMemoryView_GET_BASE')
-@cpython_api([PyObject], lltype.Ptr(Py_buffer), error=CANNOT_FAIL)
+@cpython_api([PyObject], Py_bufferP, error=CANNOT_FAIL)
def PyMemoryView_GET_BUFFER(space, w_obj):
"""Return a pointer to the buffer-info structure wrapped by the given
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)
if not isinstance(w_obj, W_MemoryView):
- return view
+ return lltype.nullptr(Py_buffer)
+ py_memobj = rffi.cast(PyMemoryViewObject, as_pyobj(space, w_obj)) # no
inc_ref
+ view = py_memobj.c_view
ndim = w_obj.buf.getndim()
if ndim >= Py_MAX_NDIMS:
# XXX warn?
@@ -173,8 +217,5 @@
view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(space.str_w(w_s),
track_allocation=False))
rffi.setintfield(view, 'c_readonly', 1)
isstr = True
- # XXX leaks the view object and never decrefs the view.c_obj
- # In cpython the view is a field of the PyMemoryViewObject
- # and view.obj is decrefed in memory_dealloc
return view
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -356,7 +356,7 @@
with lltype.scoped_alloc(Py_buffer) as pybuf:
pybuf.c_buf = self.ptr
pybuf.c_len = self.size
- pybuf.c_ndim = rffi.cast(rffi.INT, self.ndim)
+ pybuf.c_ndim = rffi.cast(rffi.INT_real, self.ndim)
for i in range(self.ndim):
pybuf.c_shape[i] = self.shape[i]
pybuf.c_strides[i] = self.strides[i]
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -10,11 +10,7 @@
PyMethodDef = rffi.VOIDP
PyGetSetDef = rffi.VOIDP
PyMemberDef = rffi.VOIDP
-Py_buffer = rffi.VOIDP
va_list = rffi.VOIDP
-PyDateTime_Date = rffi.VOIDP
-PyDateTime_DateTime = rffi.VOIDP
-PyDateTime_Time = rffi.VOIDP
wrapperbase = rffi.VOIDP
FILE = rffi.VOIDP
PyFileObject = rffi.VOIDP
diff --git a/pypy/module/cpyext/test/buffer_test.c
b/pypy/module/cpyext/test/buffer_test.c
--- a/pypy/module/cpyext/test/buffer_test.c
+++ b/pypy/module/cpyext/test/buffer_test.c
@@ -190,19 +190,21 @@
{
Py_buffer* view = NULL;
PyObject* obj = PyTuple_GetItem(args, 0);
+ int retval = 0;
int before_cnt = obj->ob_refcnt;
PyObject* memoryview = PyMemoryView_FromObject(obj);
if (memoryview == NULL)
return PyInt_FromLong(-1);
view = PyMemoryView_GET_BUFFER(memoryview);
- Py_DECREF(memoryview);
+ retval = view->len;
+ Py_DECREF(memoryview); /* view is no longer valid */
if (obj->ob_refcnt != before_cnt)
{
PyErr_SetString(PyExc_RuntimeError,
"leaking view->obj from PyMemoryView_GET_BUFFER");
return NULL;
}
- return PyInt_FromLong(view->len);
+ return PyInt_FromLong(retval);
}
/* Copied from numpy tests */
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
@@ -20,16 +20,16 @@
def test_frombuffer(self, space, api):
w_buf = space.newbuffer(StringBuffer("hello"))
w_memoryview = api.PyMemoryView_FromObject(w_buf)
- w_view = api.PyMemoryView_GET_BUFFER(w_memoryview)
- assert w_view.c_ndim == 1
- f = rffi.charp2str(w_view.c_format)
+ view = api.PyMemoryView_GET_BUFFER(w_memoryview)
+ assert view.c_ndim == 1
+ f = rffi.charp2str(view.c_format)
assert f == 'B'
- assert w_view.c_shape[0] == 5
- assert w_view.c_strides[0] == 1
- assert w_view.c_len == 5
- o = rffi.charp2str(w_view.c_buf)
+ assert view.c_shape[0] == 5
+ assert view.c_strides[0] == 1
+ assert view.c_len == 5
+ o = rffi.charp2str(view.c_buf)
assert o == 'hello'
- w_mv = api.PyMemoryView_FromBuffer(w_view)
+ w_mv = api.PyMemoryView_FromBuffer(view)
for f in ('format', 'itemsize', 'ndim', 'readonly',
'shape', 'strides', 'suboffsets'):
w_f = space.wrap(f)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit