Workaround for old libffi versions is added.
Module ctypes now supports C11 double complex only with libffi >= 3.3.0.
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
self.assertEqual(lib.my_sqrt(2.0), math.sqrt(2.0))
@unittest.skipUnless(hasattr(ctypes, "c_double_complex"),
- "requires C11 complex type")
+ "requires C11 complex type and libffi >= 3.3.0")
def test_csqrt(self):
lib.my_csqrt.argtypes = ctypes.c_double_complex,
lib.my_csqrt.restype = ctypes.c_double_complex
--- /dev/null
+Workaround for old libffi versions is added. Module ctypes supports
+:c:expr:`double complex` only with libffi >= 3.3.0. Patch by Mikhail Efimov.
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dd4d9646c56f43a9]*/
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdCEFfuzZqQPXOv?g";
#else
static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g";
#include <Python.h>
-#include <ffi.h> // FFI_TARGET_HAS_COMPLEX_TYPE
-
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
# include "../_complex.h" // csqrt()
# undef I // for _ctypes_test_generated.c.h
#endif
return sqrt(a);
}
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
EXPORT(double complex) my_csqrt(double complex a)
{
return csqrt(a);
#include "pycore_global_objects.h"// _Py_ID()
#include "pycore_traceback.h" // _PyTraceback_Add()
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#include "../_complex.h" // complex
#endif
double d;
float f;
void *p;
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
double complex C;
float complex E;
long double complex F;
#include <ffi.h>
#include "ctypes.h"
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
# include "../_complex.h" // complex
#endif
return PyFloat_FromDouble(val);
}
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
static PyObject *
C_set(void *ptr, PyObject *value, Py_ssize_t size)
{
{ 'B', B_set, B_get, NULL},
{ 'c', c_set, c_get, NULL},
{ 'd', d_set, d_get, NULL, d_set_sw, d_get_sw},
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
{ 'C', C_set, C_get, NULL},
{ 'E', E_set, E_get, NULL},
{ 'F', F_set, F_get, NULL},
case 'B': fd->pffi_type = &ffi_type_uchar; break;
case 'c': fd->pffi_type = &ffi_type_schar; break;
case 'd': fd->pffi_type = &ffi_type_double; break;
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
case 'C': fd->pffi_type = &ffi_type_complex_double; break;
case 'E': fd->pffi_type = &ffi_type_complex_float; break;
case 'F': fd->pffi_type = &ffi_type_complex_longdouble; break;
# include <alloca.h>
#endif
-#include <ffi.h> // FFI_TARGET_HAS_COMPLEX_TYPE
-
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_typeobject.h" // _PyType_GetModuleState()
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
# include "../_complex.h" // complex
#endif
double d;
float f;
void *p;
-#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
+#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
double complex C;
float complex E;
long double complex F;
+fi
+
+# Check for libffi with real complex double support.
+# This is a workaround, since FFI_TARGET_HAS_COMPLEX_TYPE was defined in libffi v3.2.1,
+# but real support was provided only in libffi v3.3.0.
+# See https://github.com/python/cpython/issues/125206 for more details.
+#
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking libffi has complex type support" >&5
+printf %s "checking libffi has complex type support... " >&6; }
+if test ${ac_cv_ffi_complex_double_supported+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_cc="$CC"
+CC="$CC -lffi"
+if test "$cross_compiling" = yes
+then :
+ ac_cv_ffi_complex_double_supported=no
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <complex.h>
+#include <ffi.h>
+int z_is_expected(double complex z)
+{
+ const double complex expected = CMPLX(1.25, -0.5);
+ return z == expected;
+}
+int main(void)
+{
+ double complex z = 1.25 - 0.5 * I;
+ ffi_type *args[1] = {&ffi_type_complex_double};
+ void *values[1] = {&z};
+ ffi_cif cif;
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_sint, args) != FFI_OK)
+ {
+ return 2;
+ }
+ ffi_arg rc;
+ ffi_call(&cif, FFI_FN(z_is_expected), &rc, values);
+ return !rc;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ ac_cv_ffi_complex_double_supported=yes
+else $as_nop
+ ac_cv_ffi_complex_double_supported=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+CC="$ac_save_cc"
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_complex_double_supported" >&5
+printf "%s\n" "$ac_cv_ffi_complex_double_supported" >&6; }
+if test "$ac_cv_ffi_complex_double_supported" = "yes"; then
+
+printf "%s\n" "#define Py_FFI_SUPPORT_C_COMPLEX 1" >>confdefs.h
+
fi
# Check for use of the system libmpdec library
])
])
+# Check for libffi with real complex double support.
+# This is a workaround, since FFI_TARGET_HAS_COMPLEX_TYPE was defined in libffi v3.2.1,
+# but real support was provided only in libffi v3.3.0.
+# See https://github.com/python/cpython/issues/125206 for more details.
+#
+AC_CACHE_CHECK([libffi has complex type support], [ac_cv_ffi_complex_double_supported],
+[ac_save_cc="$CC"
+CC="$CC -lffi"
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <complex.h>
+#include <ffi.h>
+int z_is_expected(double complex z)
+{
+ const double complex expected = CMPLX(1.25, -0.5);
+ return z == expected;
+}
+int main(void)
+{
+ double complex z = 1.25 - 0.5 * I;
+ ffi_type *args[1] = {&ffi_type_complex_double};
+ void *values[1] = {&z};
+ ffi_cif cif;
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_sint, args) != FFI_OK)
+ {
+ return 2;
+ }
+ ffi_arg rc;
+ ffi_call(&cif, FFI_FN(z_is_expected), &rc, values);
+ return !rc;
+}
+]])], [ac_cv_ffi_complex_double_supported=yes],
+[ac_cv_ffi_complex_double_supported=no],
+[ac_cv_ffi_complex_double_supported=no])
+CC="$ac_save_cc"])
+if test "$ac_cv_ffi_complex_double_supported" = "yes"; then
+ AC_DEFINE([Py_FFI_SUPPORT_C_COMPLEX], [1],
+ [Defined if _Complex C type can be used with libffi.])
+fi
+
# Check for use of the system libmpdec library
AC_MSG_CHECKING([for --with-system-libmpdec])
AC_ARG_WITH(
/* Defined if Python is built as a shared library. */
#undef Py_ENABLE_SHARED
+/* Defined if _Complex C type can be used with libffi. */
+#undef Py_FFI_SUPPORT_C_COMPLEX
+
/* Define if you want to disable the GIL */
#undef Py_GIL_DISABLED