Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r77246:2ce86180028c
Date: 2015-05-09 12:46 +0200
http://bitbucket.org/pypy/pypy/changeset/2ce86180028c/

Log:    ffi.from_buffer()

diff --git a/pypy/module/_cffi_backend/ffi_obj.py 
b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -7,7 +7,8 @@
 
 from pypy.module._cffi_backend import parse_c_type, realize_c_type
 from pypy.module._cffi_backend import newtype, cerrno, ccallback, ctypearray
-from pypy.module._cffi_backend import ctypestruct, ctypeptr, handle, cbuffer
+from pypy.module._cffi_backend import ctypestruct, ctypeptr, handle
+from pypy.module._cffi_backend import cbuffer, func
 from pypy.module._cffi_backend.ctypeobj import W_CType
 from pypy.module._cffi_backend.cdataobj import W_CData
 
@@ -219,6 +220,19 @@
         return w_ctype.cast(w_ob)
 
 
+    def descr_from_buffer(self, w_python_buffer):
+        """\
+Return a <cdata 'char[]'> that points to the data of the given Python
+object, which must support the buffer interface.  Note that this is
+not meant to be used on the built-in types str, unicode, or bytearray
+(you can build 'char[]' arrays explicitly) but only on objects
+containing large quantities of raw data in some other format, like
+'array.array' or numpy arrays."""
+        #
+        w_ctchara = newtype._new_chara_type(self.space)
+        return func.from_buffer(self.space, w_ctchara, w_python_buffer)
+
+
     @unwrap_spec(w_arg=W_CData)
     def descr_from_handle(self, w_arg):
         """\
@@ -399,7 +413,7 @@
         buffer      = interp2app(W_FFIObject.descr_buffer),
         callback    = interp2app(W_FFIObject.descr_callback),
         cast        = interp2app(W_FFIObject.descr_cast),
-        #from_buffer = interp2app(W_FFIObject.descr_from_buffer),
+        from_buffer = interp2app(W_FFIObject.descr_from_buffer),
         from_handle = interp2app(W_FFIObject.descr_from_handle),
         #gc          = interp2app(W_FFIObject.descr_gc),
         getctype    = interp2app(W_FFIObject.descr_getctype),
diff --git a/pypy/module/_cffi_backend/newtype.py 
b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -25,6 +25,7 @@
     def __init__(self, space):
         self.ctvoid = None      # There can be only one
         self.ctvoidp = None     # Cache for self.pointers[self.ctvoid]
+        self.ctchara = None     # Cache for self.arrays[charp, -1]
         self.primitives = {}    # Keys: name
         self.pointers = {}      # Keys: base_ctype
         self.arrays = {}        # Keys: (ptr_ctype, length_or_-1)
@@ -46,7 +47,9 @@
 
 def _clean_cache(space):
     "NOT_RPYTHON"
+    from pypy.module._cffi_backend.realize_c_type import RealizeCache
     space.fromcache(UniqueCache).__init__(space)
+    space.fromcache(RealizeCache).__init__(space)
 
 # ____________________________________________________________
 
@@ -548,6 +551,16 @@
         unique_cache.ctvoidp = new_pointer_type(space, new_void_type(space))
     return unique_cache.ctvoidp
 
[email protected]
+def _new_chara_type(space):
+    unique_cache = space.fromcache(UniqueCache)
+    if unique_cache.ctchara is None:
+        ctchar = new_primitive_type(space, "char")
+        ctcharp = new_pointer_type(space, ctchar)
+        ctchara = _new_array_type(space, ctcharp, length=-1)
+        unique_cache.ctchara = ctchara
+    return unique_cache.ctchara
+
 # ____________________________________________________________
 
 @unwrap_spec(name=str, w_basectype=ctypeobj.W_CType)
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -1,7 +1,7 @@
 from pypy.module._cffi_backend.newtype import _clean_cache
 
 class AppTestFFIObj:
-    spaceconfig = dict(usemodules=('_cffi_backend', ))
+    spaceconfig = dict(usemodules=('_cffi_backend', 'array'))
 
     def teardown_method(self, meth):
         _clean_cache(self.space)
@@ -187,3 +187,13 @@
         ffi = _cffi1_backend.FFI()
         a = ffi.new("signed char[]", [5, 6, 7])
         assert ffi.buffer(a)[:] == '\x05\x06\x07'
+
+    def test_ffi_from_buffer(self):
+        import _cffi_backend as _cffi1_backend
+        import array
+        ffi = _cffi1_backend.FFI()
+        a = array.array('H', [10000, 20000, 30000])
+        c = ffi.from_buffer(a)
+        assert ffi.typeof(c) is ffi.typeof("char[]")
+        ffi.cast("unsigned short *", c)[1] += 500
+        assert list(a) == [10000, 20500, 30000]
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to