[pypy-commit] cffi default: Test and fix: from callbacks with 'void' as the result type, you should

arigo noreply at buildbot.pypy.org
Thu Jul 5 19:08:11 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r581:5380328af7ce
Date: 2012-07-05 19:07 +0200
http://bitbucket.org/cffi/cffi/changeset/5380328af7ce/

Log:	Test and fix: from callbacks with 'void' as the result type, you
	should really return None and not anything else.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3141,9 +3141,15 @@
     if (py_res == NULL)
         goto error;
 
-    if (SIGNATURE(0)->ct_size > 0)
+    if (SIGNATURE(0)->ct_size > 0) {
         if (convert_from_object(result, SIGNATURE(0), py_res) < 0)
             goto error;
+    }
+    else if (py_res != Py_None) {
+        PyErr_SetString(PyExc_TypeError, "callback with the return type 'void'"
+                                         " must return None");
+        goto error;
+    }
  done:
     Py_XDECREF(py_args);
     Py_XDECREF(py_res);
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -284,6 +284,9 @@
                 return None
             @staticmethod
             def _to_ctypes(novalue):
+                if novalue is not None:
+                    raise TypeError("None expected, got %s object" %
+                                    (type(novalue).__name__,))
                 return None
         CTypesVoid._fix_class()
         return CTypesVoid
@@ -734,7 +737,7 @@
                                 # .value: http://bugs.python.org/issue1574593
                         else:
                             res2 = None
-                    print repr(res2)
+                    #print repr(res2)
                     return res2
                 if issubclass(BResult, CTypesGenericPtr):
                     # The only pointers callbacks can return are void*s:
diff --git a/testing/test_function.py b/testing/test_function.py
--- a/testing/test_function.py
+++ b/testing/test_function.py
@@ -1,6 +1,6 @@
 import py
 from cffi import FFI
-import math, os, sys
+import math, os, sys, StringIO
 from cffi.backend_ctypes import CTypesBackend
 
 
@@ -195,6 +195,25 @@
         res = fd.getvalue()
         assert res == 'world\n'
 
+    def test_callback_returning_void(self):
+        ffi = FFI(backend=self.Backend())
+        for returnvalue in [None, 42]:
+            def cb():
+                return returnvalue
+            fptr = ffi.callback("void(*)(void)", cb)
+            old_stderr = sys.stderr
+            try:
+                sys.stderr = StringIO.StringIO()
+                returned = fptr()
+                printed = sys.stderr.getvalue()
+            finally:
+                sys.stderr = old_stderr
+            assert returned is None
+            if returnvalue is None:
+                assert printed == ''
+            else:
+                assert "None" in printed
+
     def test_passing_array(self):
         ffi = FFI(backend=self.Backend())
         ffi.cdef("""


More information about the pypy-commit mailing list