1. Pypy
  2. Untitled project
  3. pypy

Commits

Antonio Cuni  committed 6566e81

make sure that ctypes arrays are convertible to pointers, and that we can pass them as arguments in the fast path

  • Participants
  • Parent commits a8321d3
  • Branches default

Comments (0)

Files changed (5)

File lib_pypy/_ctypes/array.py

View file
-
+import _ffi
 import _rawffi
 
 from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof
 from _ctypes.basics import keepalive_key, store_reference, ensure_objects
-from _ctypes.basics import CArgObject
+from _ctypes.basics import CArgObject, as_ffi_pointer
 
 class ArrayMeta(_CDataMeta):
     def __new__(self, name, cls, typedict):
     def _to_ffi_param(self):
         return self._get_buffer_value()
 
+    def _as_ffi_pointer_(self, ffitype):
+        return as_ffi_pointer(self, ffitype)
+
 ARRAY_CACHE = {}
 
 def create_array_type(base, length):
             _type_ = base
         )
         cls = ArrayMeta(name, (Array,), tpdict)
+        cls._ffiargtype = _ffi.types.Pointer(base.get_ffi_argtype())
         ARRAY_CACHE[key] = cls
         return cls

File lib_pypy/_ctypes/basics.py

View file
     }
 
 
+# called from primitive.py, pointer.py, array.py
+def as_ffi_pointer(value, ffitype):
+    my_ffitype = type(value).get_ffi_argtype()
+    # for now, we always allow types.pointer, else a lot of tests
+    # break. We need to rethink how pointers are represented, though
+    if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
+        raise ArgumentError("expected %s instance, got %s" % (type(value),
+                                                              ffitype))
+    return value._get_buffer_value()
+
+
 # used by "byref"
 from _ctypes.pointer import pointer

File lib_pypy/_ctypes/pointer.py

View file
 import _ffi
 from _ctypes.basics import _CData, _CDataMeta, cdata_from_address, ArgumentError
 from _ctypes.basics import keepalive_key, store_reference, ensure_objects
-from _ctypes.basics import sizeof, byref
+from _ctypes.basics import sizeof, byref, as_ffi_pointer
 from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
      array_slice_setitem
 
     def _as_ffi_pointer_(self, ffitype):
         return as_ffi_pointer(self, ffitype)
 
-def as_ffi_pointer(value, ffitype):
-    my_ffitype = type(value).get_ffi_argtype()
-    # for now, we always allow types.pointer, else a lot of tests
-    # break. We need to rethink how pointers are represented, though
-    if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
-        raise ArgumentError("expected %s instance, got %s" % (type(value),
-                                                              ffitype))
-    return value._get_buffer_value()
 
 def _cast_addr(obj, _, tp):
     if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):

File pypy/module/test_lib_pypy/ctypes_tests/test_fastpath.py

View file
         tf_b.errcheck = errcheck
         assert tf_b(-126) == 'hello'
 
+    def test_array_to_ptr(self):
+        ARRAY = c_int * 8
+        func = dll._testfunc_ai8
+        func.restype = POINTER(c_int)
+        func.argtypes = [ARRAY]
+        array = ARRAY(1, 2, 3, 4, 5, 6, 7, 8)
+        ptr = func(array)
+        assert ptr[0] == 1
+        assert ptr[7] == 8
+
 
 class TestFallbackToSlowpath(BaseCTypesTestChecker):
 

File pypy/module/test_lib_pypy/ctypes_tests/test_prototypes.py

View file
         def func(): pass
         CFUNCTYPE(None, c_int * 3)(func)
 
+    def test_array_to_ptr_wrongtype(self):
+        ARRAY = c_byte * 8
+        func = testdll._testfunc_ai8
+        func.restype = POINTER(c_int)
+        func.argtypes = [c_int * 8]
+        array = ARRAY(1, 2, 3, 4, 5, 6, 7, 8)
+        py.test.raises(ArgumentError, "func(array)")
+
 ################################################################
 
 if __name__ == '__main__':