mirror of https://github.com/python/cpython
gh-125206: Bug in ctypes with old libffi is fixed (#125322)
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>
This commit is contained in:
parent
54c6fcbefd
commit
aac89b54c5
|
@ -23,7 +23,7 @@ class LibTest(unittest.TestCase):
|
||||||
self.assertEqual(lib.my_sqrt(2.0), math.sqrt(2.0))
|
self.assertEqual(lib.my_sqrt(2.0), math.sqrt(2.0))
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(ctypes, "c_double_complex"),
|
@unittest.skipUnless(hasattr(ctypes, "c_double_complex"),
|
||||||
"requires C11 complex type")
|
"requires C11 complex type and libffi >= 3.3.0")
|
||||||
def test_csqrt(self):
|
def test_csqrt(self):
|
||||||
lib.my_csqrt.argtypes = ctypes.c_double_complex,
|
lib.my_csqrt.argtypes = ctypes.c_double_complex,
|
||||||
lib.my_csqrt.restype = ctypes.c_double_complex
|
lib.my_csqrt.restype = ctypes.c_double_complex
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Workaround for old libffi versions is added. Module ctypes supports
|
||||||
|
:c:expr:`double complex` only with libffi >= 3.3.0. Patch by Mikhail Efimov.
|
|
@ -1747,7 +1747,7 @@ class _ctypes.c_void_p "PyObject *" "clinic_state_sub()->PyCSimpleType_Type"
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dd4d9646c56f43a9]*/
|
/*[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";
|
static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdCEFfuzZqQPXOv?g";
|
||||||
#else
|
#else
|
||||||
static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g";
|
static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g";
|
||||||
|
|
|
@ -13,9 +13,7 @@
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
|
||||||
#include <ffi.h> // FFI_TARGET_HAS_COMPLEX_TYPE
|
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
|
||||||
|
|
||||||
#if defined(Py_HAVE_C_COMPLEX) && defined(FFI_TARGET_HAS_COMPLEX_TYPE)
|
|
||||||
# include "../_complex.h" // csqrt()
|
# include "../_complex.h" // csqrt()
|
||||||
# undef I // for _ctypes_test_generated.c.h
|
# undef I // for _ctypes_test_generated.c.h
|
||||||
#endif
|
#endif
|
||||||
|
@ -449,7 +447,7 @@ EXPORT(double) my_sqrt(double a)
|
||||||
return sqrt(a);
|
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)
|
EXPORT(double complex) my_csqrt(double complex a)
|
||||||
{
|
{
|
||||||
return csqrt(a);
|
return csqrt(a);
|
||||||
|
|
|
@ -105,7 +105,7 @@ module _ctypes
|
||||||
#include "pycore_global_objects.h"// _Py_ID()
|
#include "pycore_global_objects.h"// _Py_ID()
|
||||||
#include "pycore_traceback.h" // _PyTraceback_Add()
|
#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
|
#include "../_complex.h" // complex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -655,7 +655,7 @@ union result {
|
||||||
double d;
|
double d;
|
||||||
float f;
|
float f;
|
||||||
void *p;
|
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;
|
double complex C;
|
||||||
float complex E;
|
float complex E;
|
||||||
long double complex F;
|
long double complex F;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
#include "ctypes.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
|
# include "../_complex.h" // complex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -972,7 +972,7 @@ d_get(void *ptr, Py_ssize_t size)
|
||||||
return PyFloat_FromDouble(val);
|
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 *
|
static PyObject *
|
||||||
C_set(void *ptr, PyObject *value, Py_ssize_t size)
|
C_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
{
|
{
|
||||||
|
@ -1545,7 +1545,7 @@ static struct fielddesc formattable[] = {
|
||||||
{ 'B', B_set, B_get, NULL},
|
{ 'B', B_set, B_get, NULL},
|
||||||
{ 'c', c_set, c_get, NULL},
|
{ 'c', c_set, c_get, NULL},
|
||||||
{ 'd', d_set, d_get, NULL, d_set_sw, d_get_sw},
|
{ '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},
|
{ 'C', C_set, C_get, NULL},
|
||||||
{ 'E', E_set, E_get, NULL},
|
{ 'E', E_set, E_get, NULL},
|
||||||
{ 'F', F_set, F_get, NULL},
|
{ 'F', F_set, F_get, NULL},
|
||||||
|
@ -1600,7 +1600,7 @@ _ctypes_init_fielddesc(void)
|
||||||
case 'B': fd->pffi_type = &ffi_type_uchar; break;
|
case 'B': fd->pffi_type = &ffi_type_uchar; break;
|
||||||
case 'c': fd->pffi_type = &ffi_type_schar; break;
|
case 'c': fd->pffi_type = &ffi_type_schar; break;
|
||||||
case 'd': fd->pffi_type = &ffi_type_double; 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 'C': fd->pffi_type = &ffi_type_complex_double; break;
|
||||||
case 'E': fd->pffi_type = &ffi_type_complex_float; break;
|
case 'E': fd->pffi_type = &ffi_type_complex_float; break;
|
||||||
case 'F': fd->pffi_type = &ffi_type_complex_longdouble; break;
|
case 'F': fd->pffi_type = &ffi_type_complex_longdouble; break;
|
||||||
|
|
|
@ -2,12 +2,10 @@
|
||||||
# include <alloca.h>
|
# include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ffi.h> // FFI_TARGET_HAS_COMPLEX_TYPE
|
|
||||||
|
|
||||||
#include "pycore_moduleobject.h" // _PyModule_GetState()
|
#include "pycore_moduleobject.h" // _PyModule_GetState()
|
||||||
#include "pycore_typeobject.h" // _PyType_GetModuleState()
|
#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
|
# include "../_complex.h" // complex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -388,7 +386,7 @@ struct tagPyCArgObject {
|
||||||
double d;
|
double d;
|
||||||
float f;
|
float f;
|
||||||
void *p;
|
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;
|
double complex C;
|
||||||
float complex E;
|
float complex E;
|
||||||
long double complex F;
|
long double complex F;
|
||||||
|
|
|
@ -15050,6 +15050,70 @@ LIBS=$save_LIBS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
fi
|
||||||
|
|
||||||
# Check for use of the system libmpdec library
|
# Check for use of the system libmpdec library
|
||||||
|
|
40
configure.ac
40
configure.ac
|
@ -4089,6 +4089,46 @@ AS_VAR_IF([have_libffi], [yes], [
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# 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
|
# Check for use of the system libmpdec library
|
||||||
AC_MSG_CHECKING([for --with-system-libmpdec])
|
AC_MSG_CHECKING([for --with-system-libmpdec])
|
||||||
AC_ARG_WITH(
|
AC_ARG_WITH(
|
||||||
|
|
|
@ -1685,6 +1685,9 @@
|
||||||
/* Defined if Python is built as a shared library. */
|
/* Defined if Python is built as a shared library. */
|
||||||
#undef Py_ENABLE_SHARED
|
#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 */
|
/* Define if you want to disable the GIL */
|
||||||
#undef Py_GIL_DISABLED
|
#undef Py_GIL_DISABLED
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue