[pypy-commit] cffi default: More general fix for returning pointers from callbacks in ctypes backend.

tlynn noreply at buildbot.pypy.org
Wed Jun 20 12:41:02 CEST 2012


Author: tlynn
Branch: 
Changeset: r475:8eb01069d65f
Date: 2012-06-19 21:03 +0100
http://bitbucket.org/cffi/cffi/changeset/8eb01069d65f/

Log:	More general fix for returning pointers from callbacks in ctypes
	backend.

diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -673,11 +673,23 @@
                         args2.append(BArg._from_ctypes(arg))
                     res2 = init(*args2)
                     res2 = BResult._to_ctypes(res2)
-                    if isinstance(res2, ctypes.c_void_p):
-                        # workaround for http://bugs.python.org/issue1574593
-                        res2 = res2.value
+                    if issubclass(BResult, CTypesGenericPtr):
+                        if res2:
+                            res2 = ctypes.cast(res2, ctypes.c_void_p).value
+                                # .value: http://bugs.python.org/issue1574593
+                        else:
+                            res2 = None
                     return res2
-                self._as_ctype_ptr = CTypesFunction._ctype(callback)
+                if issubclass(BResult, CTypesGenericPtr):
+                    # The only pointers callbacks can return are void*s:
+                    # http://bugs.python.org/issue5710
+                    callback_ctype = ctypes.CFUNCTYPE(
+                        ctypes.c_void_p,
+                        *[BArg._ctype for BArg in BArgs],
+                        use_errno=True)
+                else:
+                    callback_ctype = CTypesFunction._ctype
+                self._as_ctype_ptr = callback_ctype(callback)
                 self._address = ctypes.cast(self._as_ctype_ptr,
                                             ctypes.c_void_p).value
                 self._own_callback = init
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -566,6 +566,28 @@
         assert repr(res) == "<cdata 'void *'>"
         assert ffi.cast("long", res) != 0
 
+    def test_functionptr_intptr_return(self):
+        ffi = FFI(backend=self.Backend())
+        def cb():
+            return None
+        p = ffi.callback("int*(*)()", cb)
+        res = p()
+        assert res is None
+        int_ptr = ffi.new('int')
+        def cb():
+            return int_ptr
+        p = ffi.callback("int*(*)()", cb)
+        res = p()
+        assert repr(res) == "<cdata 'int *'>"
+        assert ffi.cast("long", res) != 0
+        int_array_ptr = ffi.new('int[1]')
+        def cb():
+            return int_array_ptr
+        p = ffi.callback("int*(*)()", cb)
+        res = p()
+        assert repr(res) == "<cdata 'int *'>"
+        assert ffi.cast("long", res) != 0
+
     def test_char_cast(self):
         ffi = FFI(backend=self.Backend())
         p = ffi.cast("int", '\x01')


More information about the pypy-commit mailing list