[pypy-commit] cffi sirtom67/float_complex: Test explicitly that if we try to call a function in ABI mode with a

arigo pypy.commits at gmail.com
Mon May 29 13:11:21 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: sirtom67/float_complex
Changeset: r2937:f0f90cb166e5
Date: 2017-05-29 19:10 +0200
http://bitbucket.org/cffi/cffi/changeset/f0f90cb166e5/

Log:	Test explicitly that if we try to call a function in ABI mode with a
	complex argument or return value, then we get a clear error message.
	Previously, it would still try to call libffi. But libffi doesn't
	support complex, on all platforms except a single very obscure one,
	I think. So it seems to be a better behaviour for now.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -888,7 +888,7 @@
 static Py_complex
 read_raw_complex_data(char *target, int size)
 {
-    Py_complex r = {.real=0, .imag=0};
+    Py_complex r = {0.0, 0.0};
     if (size == 2*sizeof(float)) {
         float real_part, imag_part;
         memcpy(&real_part, target + 0,             sizeof(float));
@@ -898,7 +898,7 @@
         return r;
     }
     if (size == 2*sizeof(double)) {
-        memcpy(&(r.real), target, 2*sizeof(double));
+        memcpy(&r, target, 2*sizeof(double));
         return r;
     }
     Py_FatalError("read_raw_complex_data: bad float size");
@@ -4224,14 +4224,11 @@
             goto bad_ffi_type;
     }
     else if (ptypes->flags & CT_PRIMITIVE_COMPLEX) {
-        // as of March 2017, still no libffi support for complex
-        // but it fails silently.
-        if (strcmp(ptypes->name, "float _Complex") == 0)
-            ffitype = &ffi_type_complex_float;
-        else if (strcmp(ptypes->name, "double _Complex") == 0)
-            ffitype = &ffi_type_complex_double;
-        else
-            goto bad_ffi_type;
+        /* As of March 2017, still no libffi support for complex.
+           It fails silently if we try to use ffi_type_complex_float
+           or ffi_type_complex_double.  Better not use it at all.
+         */
+        ffitype = NULL;
     }
     else {
         switch (ptypes->size) {
@@ -4925,7 +4922,7 @@
 {
     const char *place = is_result_type ? "return value" : "argument";
 
-    if (ct->ct_flags & CT_PRIMITIVE_ANY) {
+    if (ct->ct_flags & (CT_PRIMITIVE_ANY & ~CT_PRIMITIVE_COMPLEX)) {
         return (ffi_type *)ct->ct_extra;
     }
     else if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
@@ -5051,9 +5048,16 @@
         return NULL;
     }
     else {
+        char *extra = "";
+        if (ct->ct_flags & CT_PRIMITIVE_COMPLEX)
+            extra = " (the support for complex types inside libffi "
+                    "is mostly missing at this point, so CFFI only "
+                    "supports complex types as arguments or return "
+                    "value in API-mode functions)";
+
         PyErr_Format(PyExc_NotImplementedError,
-                     "ctype '%s' (size %zd) not supported as %s",
-                     ct->ct_name, ct->ct_size, place);
+                     "ctype '%s' (size %zd) not supported as %s%s",
+                     ct->ct_name, ct->ct_size, place, extra);
         return NULL;
     }
 }
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -1130,27 +1130,32 @@
     assert f(3, cast(BSChar, -3), cast(BUChar, 200), cast(BSShort, -5)) == 192
 
 def test_call_function_24():
-    py.test.skip("libffi returning nonsense silently")
     BFloat = new_primitive_type("float")
     BFloatComplex = new_primitive_type("float _Complex")
     BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False)
-    f = cast(BFunc3, _testfunc(24))
-    result = f(1.25, 5.1)
-    assert type(result) == complex
-    assert result.real == 1.25   # exact
-    assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact  
+    if 0:   # libffi returning nonsense silently, so logic disabled for now
+        f = cast(BFunc3, _testfunc(24))
+        result = f(1.25, 5.1)
+        assert type(result) == complex
+        assert result.real == 1.25   # exact
+        assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact
+    else:
+        f = cast(BFunc3, _testfunc(9))
+        py.test.raises(NotImplementedError, f, 12.3, 34.5)
 
 def test_call_function_25():
-    py.test.skip("libffi returning nonsense silently")
     BDouble = new_primitive_type("double")
     BDoubleComplex = new_primitive_type("double _Complex")
     BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False)
-    f = cast(BFunc3, _testfunc(25))
-    result = f(1.25, 5.1)
-    assert type(result) == complex
-    assert result.real == 1.25   # exact
-    assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact  
-
+    if 0:   # libffi returning nonsense silently, so logic disabled for now
+        f = cast(BFunc3, _testfunc(25))
+        result = f(1.25, 5.1)
+        assert type(result) == complex
+        assert result.real == 1.25   # exact
+        assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact
+    else:
+        f = cast(BFunc3, _testfunc(9))
+        py.test.raises(NotImplementedError, f, 12.3, 34.5)
 
 def test_cannot_call_with_a_autocompleted_struct():
     BSChar = new_primitive_type("signed char")


More information about the pypy-commit mailing list