Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r75195:9bdd174fb4e1 Date: 2015-01-01 18:47 +0100 http://bitbucket.org/pypy/pypy/changeset/9bdd174fb4e1/
Log: Implement ffi.from_buffer(). Not really tested with memoryviews, only buffers, just like in CPython for the same reasons. diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -34,6 +34,7 @@ 'newp_handle': 'handle.newp_handle', 'from_handle': 'handle.from_handle', '_get_types': 'func._get_types', + 'from_buffer': 'func.from_buffer', 'string': 'func.string', 'buffer': 'cbuffer.buffer', diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -440,6 +440,25 @@ return "handle to %s" % (self.space.str_w(w_repr),) +class W_CDataFromBuffer(W_CData): + _attrs_ = ['buf', 'length', 'w_keepalive'] + _immutable_fields_ = ['buf', 'length', 'w_keepalive'] + + def __init__(self, space, cdata, ctype, buf, w_object): + W_CData.__init__(self, space, cdata, ctype) + self.buf = buf + self.length = buf.getlength() + self.w_keepalive = w_object + + def get_array_length(self): + return self.length + + def _repr_extra(self): + w_repr = self.space.repr(self.w_keepalive) + return "buffer len %d from '%s' object" % ( + self.length, self.space.type(self.w_keepalive).name) + + W_CData.typedef = TypeDef( '_cffi_backend.CData', __module__ = '_cffi_backend', diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py --- a/pypy/module/_cffi_backend/func.py +++ b/pypy/module/_cffi_backend/func.py @@ -76,3 +76,32 @@ def _get_types(space): return space.newtuple([space.gettypefor(cdataobj.W_CData), space.gettypefor(ctypeobj.W_CType)]) + +# ____________________________________________________________ + +@unwrap_spec(w_ctype=ctypeobj.W_CType) +def from_buffer(space, w_ctype, w_x): + from pypy.module._cffi_backend import ctypearray, ctypeprim + # + if (not isinstance(w_ctype, ctypearray.W_CTypeArray) or + not isinstance(w_ctype.ctptr.ctitem, ctypeprim.W_CTypePrimitiveChar)): + raise oefmt(space.w_TypeError, + "needs 'char[]', got '%s'", w_ctype.name) + # + # xxx do we really need to implement the same mess as in CPython 2.7 + # w.r.t. buffers and memoryviews?? + try: + buf = space.readbuf_w(w_x) + except OperationError, e: + if not e.match(space, space.w_TypeError): + raise + buf = space.buffer_w(w_x, space.BUF_SIMPLE) + try: + _cdata = buf.get_raw_address() + except ValueError: + raise oefmt(space.w_TypeError, + "from_buffer() got a '%T' object, which supports the " + "buffer interface but cannot be rendered as a plain " + "raw address on PyPy", w_x) + # + return cdataobj.W_CDataFromBuffer(space, _cdata, w_ctype, buf, w_x) diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -3195,6 +3195,20 @@ ('a2', BChar, 5)], None, -1, -1, SF_PACKED) +def test_from_buffer(): + import array + a = array.array('H', [10000, 20000, 30000]) + BChar = new_primitive_type("char") + BCharP = new_pointer_type(BChar) + BCharA = new_array_type(BCharP, None) + c = from_buffer(BCharA, a) + assert typeof(c) is BCharA + assert len(c) == 6 + assert repr(c) == "<cdata 'char[]' buffer len 6 from 'array.array' object>" + p = new_pointer_type(new_primitive_type("unsigned short")) + cast(p, c)[1] += 500 + assert list(a) == [10000, 20500, 30000] + def test_version(): # this test is here mostly for PyPy assert __version__ == "0.8.6" diff --git a/pypy/module/_cffi_backend/test/test_c.py b/pypy/module/_cffi_backend/test/test_c.py --- a/pypy/module/_cffi_backend/test/test_c.py +++ b/pypy/module/_cffi_backend/test/test_c.py @@ -30,7 +30,7 @@ class AppTestC(object): """Populated below, hack hack hack.""" - spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO')) + spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO', 'array')) def setup_class(cls): testfuncs_w = [] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit