Skip to content

gh-61103: don't use native complex types in ctypes #133237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -3313,7 +3313,7 @@ MODULE_CMATH_DEPS=$(srcdir)/Modules/_math.h
MODULE_MATH_DEPS=$(srcdir)/Modules/_math.h
MODULE_PYEXPAT_DEPS=@LIBEXPAT_INTERNAL@
MODULE_UNICODEDATA_DEPS=$(srcdir)/Modules/unicodedata_db.h $(srcdir)/Modules/unicodename_db.h
MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h $(srcdir)/Modules/_complex.h
MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h
MODULE__CTYPES_TEST_DEPS=$(srcdir)/Modules/_ctypes/_ctypes_test_generated.c.h
MODULE__CTYPES_MALLOC_CLOSURE=@MODULE__CTYPES_MALLOC_CLOSURE@
MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h @LIBMPDEC_INTERNAL@
Expand Down
54 changes: 0 additions & 54 deletions Modules/_complex.h

This file was deleted.

2 changes: 1 addition & 1 deletion Modules/_ctypes/_ctypes_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#endif

#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
# include "../_complex.h" // csqrt()
# include <complex.h> // csqrt()
# undef I // for _ctypes_test_generated.c.h
#endif
#include <stdio.h> // printf()
Expand Down
11 changes: 3 additions & 8 deletions Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,6 @@ module _ctypes
#include "pycore_global_objects.h"// _Py_ID()
#include "pycore_traceback.h" // _PyTraceback_Add()

#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#include "../_complex.h" // complex
#endif
#define clinic_state() (get_module_state(module))
#include "clinic/callproc.c.h"
#undef clinic_state
Expand Down Expand Up @@ -652,11 +649,9 @@ union result {
double d;
float f;
void *p;
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
double complex D;
float complex F;
long double complex G;
#endif
double D[2];
float F[2];
long double G[2];
};

struct argument {
Expand Down
45 changes: 24 additions & 21 deletions Modules/_ctypes/cfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
#include <ffi.h>
#include "ctypes.h"

#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
# include "../_complex.h" // complex
#endif

#define CTYPES_CFIELD_CAPSULE_NAME_PYMEM "_ctypes/cfield.c pymem"

/*[clinic input]
Expand Down Expand Up @@ -763,80 +759,87 @@ d_get(void *ptr, Py_ssize_t size)
return PyFloat_FromDouble(val);
}

#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#if defined(Py_FFI_SUPPORT_C_COMPLEX)

/* We don't use _Complex types here, using arrays instead, as the C11+
standard says: "Each complex type has the same representation and alignment
requirements as an array type containing exactly two elements of the
corresponding real type; the first element is equal to the real part, and
the second element to the imaginary part, of the complex number." */

/* D: double complex */
static PyObject *
D_set(void *ptr, PyObject *value, Py_ssize_t size)
{
assert(NUM_BITS(size) || (size == sizeof(double complex)));
assert(NUM_BITS(size) || (size == 2*sizeof(double)));
Py_complex c = PyComplex_AsCComplex(value);

if (c.real == -1 && PyErr_Occurred()) {
return NULL;
}
double complex x = CMPLX(c.real, c.imag);
double x[2] = {c.real, c.imag};
memcpy(ptr, &x, sizeof(x));
_RET(value);
}

static PyObject *
D_get(void *ptr, Py_ssize_t size)
{
assert(NUM_BITS(size) || (size == sizeof(double complex)));
double complex x;
assert(NUM_BITS(size) || (size == 2*sizeof(double)));
double x[2];

memcpy(&x, ptr, sizeof(x));
return PyComplex_FromDoubles(creal(x), cimag(x));
return PyComplex_FromDoubles(x[0], x[1]);
}

/* F: float complex */
static PyObject *
F_set(void *ptr, PyObject *value, Py_ssize_t size)
{
assert(NUM_BITS(size) || (size == sizeof(float complex)));
assert(NUM_BITS(size) || (size == 2*sizeof(float)));
Py_complex c = PyComplex_AsCComplex(value);

if (c.real == -1 && PyErr_Occurred()) {
return NULL;
}
float complex x = CMPLXF((float)c.real, (float)c.imag);
float x[2] = {(float)c.real, (float)c.imag};
memcpy(ptr, &x, sizeof(x));
_RET(value);
}

static PyObject *
F_get(void *ptr, Py_ssize_t size)
{
assert(NUM_BITS(size) || (size == sizeof(float complex)));
float complex x;
assert(NUM_BITS(size) || (size == 2*sizeof(float)));
float x[2];

memcpy(&x, ptr, sizeof(x));
return PyComplex_FromDoubles(crealf(x), cimagf(x));
return PyComplex_FromDoubles(x[0], x[1]);
}

/* G: long double complex */
static PyObject *
G_set(void *ptr, PyObject *value, Py_ssize_t size)
{
assert(NUM_BITS(size) || (size == sizeof(long double complex)));
assert(NUM_BITS(size) || (size == 2*sizeof(long double)));
Py_complex c = PyComplex_AsCComplex(value);

if (c.real == -1 && PyErr_Occurred()) {
return NULL;
}
long double complex x = CMPLXL(c.real, c.imag);
long double x[2] = {c.real, c.imag};
memcpy(ptr, &x, sizeof(x));
_RET(value);
}

static PyObject *
G_get(void *ptr, Py_ssize_t size)
{
assert(NUM_BITS(size) || (size == sizeof(long double complex)));
long double complex x;
assert(NUM_BITS(size) || (size == 2*sizeof(long double)));
long double x[2];

memcpy(&x, ptr, sizeof(x));
return PyComplex_FromDoubles((double)creall(x), (double)cimagl(x));
return PyComplex_FromDoubles((double)x[0], (double)x[1]);
}
#endif

Expand Down Expand Up @@ -1596,7 +1599,7 @@ for base_code, base_c_type in [
///////////////////////////////////////////////////////////////////////////

TABLE_ENTRY_SW(d, &ffi_type_double);
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#if defined(Py_FFI_SUPPORT_C_COMPLEX)
if (Py_FFI_COMPLEX_AVAILABLE) {
TABLE_ENTRY(D, &ffi_type_complex_double);
TABLE_ENTRY(F, &ffi_type_complex_float);
Expand Down
11 changes: 4 additions & 7 deletions Modules/_ctypes/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

// Do we support C99 complex types in ffi?
// For Apple's libffi, this must be determined at runtime (see gh-128156).
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
# include "../_complex.h" // complex
#if defined(Py_FFI_SUPPORT_C_COMPLEX)
# if USING_APPLE_OS_LIBFFI && defined(__has_builtin)
# if __has_builtin(__builtin_available)
# define Py_FFI_COMPLEX_AVAILABLE __builtin_available(macOS 10.15, *)
Expand Down Expand Up @@ -493,11 +492,9 @@ struct tagPyCArgObject {
double d;
float f;
void *p;
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
double complex D;
float complex F;
long double complex G;
#endif
double D[2];
float F[2];
long double G[2];
} value;
PyObject *obj;
Py_ssize_t size; /* for the 'V' tag */
Expand Down
4 changes: 2 additions & 2 deletions Modules/_struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,8 +853,8 @@ static const formatdef native_table[] = {
{'e', sizeof(short), _Alignof(short), nu_halffloat, np_halffloat},
{'f', sizeof(float), _Alignof(float), nu_float, np_float},
{'d', sizeof(double), _Alignof(double), nu_double, np_double},
{'F', 2*sizeof(float), _Alignof(float[2]), nu_float_complex, np_float_complex},
{'D', 2*sizeof(double), _Alignof(double[2]), nu_double_complex, np_double_complex},
{'F', 2*sizeof(float), _Alignof(float), nu_float_complex, np_float_complex},
{'D', 2*sizeof(double), _Alignof(double), nu_double_complex, np_double_complex},
{'P', sizeof(void *), _Alignof(void *), nu_void_p, np_void_p},
{0}
};
Expand Down
Loading