[pypy-commit] pypy issue2444: massive hack of CPyBuffer.__del__ to call bf_releasebuffer, new idea needed

mattip pypy.commits at gmail.com
Mon Dec 12 15:01:51 EST 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: issue2444
Changeset: r89034:9d872f71a438
Date: 2016-12-12 22:01 +0200
http://bitbucket.org/pypy/pypy/changeset/9d872f71a438/

Log:	massive hack of CPyBuffer.__del__ to call bf_releasebuffer, new idea
	needed

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
@@ -12,7 +12,7 @@
     getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
     ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
     cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
-    readbufferproc, getbufferproc, ssizessizeobjargproc)
+    readbufferproc, getbufferproc, releasebufferproc, ssizessizeobjargproc)
 from pypy.module.cpyext.pyobject import make_ref, Py_DecRef
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.memoryobject import fill_Py_buffer
@@ -321,8 +321,10 @@
     # Similar to Py_buffer
     _immutable_ = True
 
-    def __init__(self, ptr, size, w_obj, format='B', shape=None,
-                strides=None, ndim=1, itemsize=1, readonly=True):
+    def __init__(self, space, ptr, size, w_obj, format='B', shape=None,
+                strides=None, ndim=1, itemsize=1, readonly=True,
+                releasebuffer=None):
+        self.space = space
         self.ptr = ptr
         self.size = size
         self.w_obj = w_obj # kept alive
@@ -338,6 +340,20 @@
         self.ndim = ndim
         self.itemsize = itemsize
         self.readonly = readonly
+        self.releasebuffer = releasebuffer
+
+    def __del__(self):
+        if self.releasebuffer:
+            func_target = rffi.cast(releasebufferproc, self.releasebuffer)
+            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)
+                for i in range(self.ndim):
+                    pybuf.c_shape[i] = self.shape[i]
+                    pybuf.c_strides[i] = self.strides[i]
+                pybuf.c_format = rffi.str2charp(self.format)
+                generic_cpy_call(self.space, func_target, self.w_obj, pybuf)
 
     def getlength(self):
         return self.size
@@ -369,24 +385,35 @@
 
 def wrap_getreadbuffer(space, w_self, w_args, func):
     func_target = rffi.cast(readbufferproc, func)
+    py_obj = make_ref(space, w_self)
+    py_type = py_obj.c_ob_type
+    releasebuffer = py_type.c_tp_as_buffer and py_type.c_tp_as_buffer.c_bf_releasebuffer
     with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
         index = rffi.cast(Py_ssize_t, 0)
         size = generic_cpy_call(space, func_target, w_self, index, ptr)
         if size < 0:
             space.fromcache(State).check_and_raise_exception(always=True)
-        return space.newbuffer(CPyBuffer(ptr[0], size, w_self))
+        return space.newbuffer(CPyBuffer(space, ptr[0], size, w_self, 
+                               releasebuffer=releasebuffer))
 
 def wrap_getwritebuffer(space, w_self, w_args, func):
     func_target = rffi.cast(readbufferproc, func)
+    py_obj = make_ref(space, w_self)
+    py_type = py_obj.c_ob_type
+    releasebuffer = py_type.c_tp_as_buffer and py_type.c_tp_as_buffer.c_bf_releasebuffer
     with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
         index = rffi.cast(Py_ssize_t, 0)
         size = generic_cpy_call(space, func_target, w_self, index, ptr)
         if size < 0:
             space.fromcache(State).check_and_raise_exception(always=True)
-        return space.newbuffer(CPyBuffer(ptr[0], size, w_self, readonly=False))
+        return space.newbuffer(CPyBuffer(space, ptr[0], size, w_self, readonly=False,
+                               releasebuffer=releasebuffer))
 
 def wrap_getbuffer(space, w_self, w_args, func):
     func_target = rffi.cast(getbufferproc, func)
+    py_obj = make_ref(space, w_self)
+    py_type = py_obj.c_ob_type
+    releasebuffer = py_type.c_tp_as_buffer and py_type.c_tp_as_buffer.c_bf_releasebuffer
     with lltype.scoped_alloc(Py_buffer) as pybuf:
         _flags = 0
         if space.len_w(w_args) > 0:
@@ -407,10 +434,11 @@
             format = rffi.charp2str(pybuf.c_format)
         else:
             format = 'B'
-        return space.newbuffer(CPyBuffer(ptr, size, w_self, format=format,
+        return space.newbuffer(CPyBuffer(space, ptr, size, w_self, format=format,
                             ndim=ndim, shape=shape, strides=strides,
                             itemsize=pybuf.c_itemsize,
-                            readonly=widen(pybuf.c_readonly)))
+                            readonly=widen(pybuf.c_readonly),
+                            releasebuffer = releasebuffer))
 
 def get_richcmp_func(OP_CONST):
     def inner(space, w_self, w_args, func):
diff --git a/pypy/module/cpyext/typeobjectdefs.py b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -60,7 +60,7 @@
 segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
 charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
 getbufferproc = P(FT([PyO, Py_bufferP, rffi.INT_real], rffi.INT_real))
-releasebufferproc = rffi.VOIDP
+releasebufferproc = P(FT([PyO, Py_bufferP], Void))
 
 
 PyGetSetDef = cpython_struct("PyGetSetDef", (


More information about the pypy-commit mailing list