Commits

Amaury Forgeot d'Arc committed 033e22d

cpyext: implement PyMemoryView_FromBuffer

Comments (0)

Files changed (4)

pypy/module/cpyext/buffer.py

-from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
     cpython_api, CANNOT_FAIL, Py_buffer)
-from pypy.module.cpyext.pyobject import PyObject
+from pypy.module.cpyext.pyobject import PyObject, Py_DecRef
+from pypy.interpreter import buffer
 
 @cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real, error=CANNOT_FAIL)
 def PyBuffer_IsContiguous(space, view, fortran):
     (fortran is 'A').  Return 0 otherwise."""
     # PyPy only supports contiguous Py_buffers for now.
     return 1
+
+class CBufferMixin(object):
+    _mixin_ = True
+
+    def __init__(self, space, c_buf, c_len, w_obj):
+        self.space = space
+        self.c_buf = c_buf
+        self.c_len = c_len
+        self.w_obj = w_obj
+
+    def __del__(self):
+        Py_DecRef(self.space, self.w_obj)
+
+    def getlength(self):
+        return self.c_len
+
+    def getitem(self, index):
+        return self.c_buf[index]
+
+    def as_str(self):
+        return rffi.charpsize2str(self.c_buf, self.c_len)
+        
+class CBuffer(CBufferMixin, buffer.Buffer):
+    pass

pypy/module/cpyext/memoryobject.py

-from pypy.module.cpyext.api import cpython_api
-from pypy.module.cpyext.pyobject import PyObject
+from pypy.module.cpyext.api import cpython_api, Py_buffer
+from pypy.module.cpyext.pyobject import PyObject, from_ref
+from pypy.module.cpyext.buffer import CBuffer
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.__builtin__.interp_memoryview import W_MemoryView
 
 @cpython_api([PyObject], PyObject)
 def PyMemoryView_FromObject(space, w_obj):
     return space.call_method(space.builtin, "memoryview", w_obj)
+
+@cpython_api([lltype.Ptr(Py_buffer)], PyObject)
+def PyMemoryView_FromBuffer(space, view):
+    """Create a memoryview object wrapping the given buffer structure view.
+    The memoryview object then owns the buffer represented by view, which
+    means you shouldn't try to call PyBuffer_Release() yourself: it
+    will be done on deallocation of the memoryview object."""
+    w_obj = from_ref(space, view.c_obj)
+    buf = CBuffer(space, view.c_buf, view.c_len, w_obj)
+    return space.wrap(W_MemoryView(space.wrap(buf)))

pypy/module/cpyext/stubs.py

     raise NotImplementedError
     
 
-@cpython_api([Py_buffer], PyObject)
-def PyMemoryView_FromBuffer(space, view):
-    """Create a memoryview object wrapping the given buffer structure view.
-    The memoryview object then owns the buffer represented by view, which
-    means you shouldn't try to call PyBuffer_Release() yourself: it
-    will be done on deallocation of the memoryview object."""
-    raise NotImplementedError
-    
-
 @cpython_api([PyObject, rffi.INT_real, lltype.Char], PyObject)
 def PyMemoryView_GetContiguous(space, obj, buffertype, order):
     """Create a memoryview object to a contiguous chunk of memory (in either

pypy/module/cpyext/test/test_memoryobject.py

 import py
 from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 
 class TestMemoryViewObject(BaseApiTest):
     def test_fromobject(self, space, api):
         w_view = api.PyMemoryView_FromObject(w_hello)
         w_bytes = space.call_method(w_view, "tobytes")
         assert space.unwrap(w_bytes) == "hello"
+
+class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
+    def test_fillWithObject(self):
+        module = self.import_extension('foo', [
+                ("fillinfo", "METH_VARARGS",
+                 """
+                 Py_buffer buf;
+                 PyObject *str = PyBytes_FromString("hello, world.");
+                 PyObject *result;
+
+                 if (PyBuffer_FillInfo(&buf, str, PyBytes_AsString(str), 13,
+                                       0, 0)) {
+                     return NULL;
+                 }
+
+                 /* Get rid of our own reference to the object, but
+                  * the Py_buffer should still have a reference.
+                  */
+                 Py_DECREF(str);
+
+                 return PyMemoryView_FromBuffer(&buf);
+                 """)])
+        result = module.fillinfo()
+        assert b"hello, world." == result
+
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.