Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: py3k Changeset: r59261:033e22d48bf2 Date: 2012-12-02 23:36 +0100 http://bitbucket.org/pypy/pypy/changeset/033e22d48bf2/
Log: cpyext: implement PyMemoryView_FromBuffer 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,8 +1,8 @@ -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): @@ -11,3 +11,27 @@ (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 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,6 +1,19 @@ -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))) 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 @@ -1610,15 +1610,6 @@ 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 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 @@ -1,5 +1,6 @@ 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): @@ -11,3 +12,29 @@ 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 + + _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit