Repository navigation
Add support for C99 complex type (_Complex) to the struct module #121249
Copy link
Copy link
Closed
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtype-featureA feature request or enhancementA feature request or enhancement
Description
Feature or enhancement
Proposal:
The struct module has support for float and double types, so at least there should be also float _Complex and double _Complex. I'll work on a patch.
Initial version
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index d2e6a8bfc8..d941036719 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -208,6 +208,7 @@ class c_longdouble(_SimpleCData):
try:
class c_double_complex(_SimpleCData):
_type_ = "C"
+ _check_size(c_double_complex)
except AttributeError:
pass
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 6a68478dd4..caf4975413 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -12,6 +12,9 @@
#include "pycore_long.h" // _PyLong_AsByteArray()
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#ifdef Py_HAVE_C_COMPLEX
+# include "_complex.h" // complex
+#endif
#include <stddef.h> // offsetof()
/*[clinic input]
@@ -80,6 +83,9 @@ typedef struct { char c; int x; } st_int;
typedef struct { char c; long x; } st_long;
typedef struct { char c; float x; } st_float;
typedef struct { char c; double x; } st_double;
+#ifdef Py_HAVE_C_COMPLEX
+typedef struct { char c; double complex x; } st_double_complex;
+#endif
typedef struct { char c; void *x; } st_void_p;
typedef struct { char c; size_t x; } st_size_t;
typedef struct { char c; _Bool x; } st_bool;
@@ -89,6 +95,9 @@ typedef struct { char c; _Bool x; } st_bool;
#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
+#ifdef Py_HAVE_C_COMPLEX
+#define DOUBLE_COMPLEX_ALIGN (sizeof(st_double_complex) - sizeof(double complex))
+#endif
#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t))
#define BOOL_ALIGN (sizeof(st_bool) - sizeof(_Bool))
@@ -518,6 +527,17 @@ nu_double(_structmodulestate *state, const char *p, const formatdef *f)
return PyFloat_FromDouble(x);
}
+#ifdef Py_HAVE_C_COMPLEX
+static PyObject *
+nu_double_complex(_structmodulestate *state, const char *p, const formatdef *f)
+{
+ double complex x;
+
+ memcpy(&x, p, sizeof(x));
+ return PyComplex_FromDoubles(creal(x), cimag(x));
+}
+#endif
+
static PyObject *
nu_void_p(_structmodulestate *state, const char *p, const formatdef *f)
{
@@ -791,6 +811,24 @@ np_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
return 0;
}
+#ifdef Py_HAVE_C_COMPLEX
+static int
+np_double_complex(_structmodulestate *state, char *p, PyObject *v,
+ const formatdef *f)
+{
+ Py_complex c = PyComplex_AsCComplex(v);
+ double complex x = CMPLX(c.real, c.imag);
+
+ if (c.real == -1 && PyErr_Occurred()) {
+ PyErr_SetString(state->StructError,
+ "required argument is not a complex");
+ return -1;
+ }
+ memcpy(p, (char *)&x, sizeof(x));
+ return 0;
+}
+#endif
+
static int
np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
{
@@ -829,6 +867,9 @@ static const formatdef native_table[] = {
{'e', sizeof(short), SHORT_ALIGN, nu_halffloat, np_halffloat},
{'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
{'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
+#ifdef Py_HAVE_C_COMPLEX
+ {'C', sizeof(double complex), DOUBLE_COMPLEX_ALIGN, nu_double_complex, np_double_complex},
+#endif
{'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
{0}
};Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Linked PRs
- gh-121249: Support _Complex types in the struct module #121613
- gh-121249: Note struct module changes in What's New #131867
- gh-121249: adjust formatting codes for complex types in struct/ctypes modules #132827
- gh-121249: fix naming of struct tagPyCArgObject members #132863
- gh-121249: unconditionally support
complextypes instruct#132864 - gh-121249: fix complex formatting codes in the struct docs (note 10) #133249
- gh-121249: remove F/D type codes from table in the struct module #149346
- [3.15] gh-121249: Soft deprecate F and D struct format types (#149346) #152274
- gh-121249: Deprecate using F/D type codes in the struct module #152309
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtype-featureA feature request or enhancementA feature request or enhancement
Projects
- StatusShow more project fieldsDone
Activity
pythongh-121249: Support _Complex types in the struct module
pythongh-121249: Support _Complex types in the struct module
pythongh-121249: Support _Complex types in the struct module
gh-121249: Support _Complex types in the struct module (#121613)
vstinner commentedon Oct 7, 2024
Implemented by change 7487db4.
efimov-mikhail commentedon Oct 10, 2024
IMO, we should provide a support for long double complex in struct module.
For now there is a little inconvience:
skirpichev commentedon Oct 10, 2024
But we don't have support for long double here. I don't know for sure why it wasn't here historically, will dig into it.
Probably together with support for long double - a support for long double complex will also make sense.
efimov-mikhail commentedon Oct 10, 2024
Even long double is not supported?
Probably, there is not by intention, just because a lack of time.
It seems like support for long double complex now is partial.
In come cases they are allowed (call csqrtl, for example), but in other they aren't (struct module).
I've just wanted to emphasize this.
skirpichev commentedon Oct 10, 2024
Maybe is. The long double is a more complex beast: https://en.wikipedia.org/wiki/Long_double
vstinner commentedon Oct 10, 2024
I would prefer to not support long double, it looks complicated for little usage.
skirpichev commentedon Oct 12, 2024
@vstinner, I don't think it's too complicated. On technical side we, probably, have to add only PyFloat_Pack/Unpack16() and PyFloat_Pack/Unpack10() functions for the IEEE 754 quadruples and the x86 extended precision format. Say, "m" and "o" format codes for the struct module.
These are popular standards and it's nice to have conversion helpers, available in the Python.
The "F" format for the long double complex type will be implemented like "E" and "C", i.e. using IEEE binary128.
If that sounds, I'll open an issue. Hardly discussion on d.p.o does make sense.
pythongh-121249: add news about struct module
gh-121249: Note struct module changes in What's New (#131867)
26 remaining items
skirpichev commentedon May 4, 2025
I think this is done. The ctypes module has own issue.
pythongh-121249: unconditionally support `complex` types in `struct` (p…
pythongh-121249: fix complex formatting codes in the struct docs (not…
gh-121249: Soft deprecate F and D struct format types (#149346)
[3.15] gh-121249: Soft deprecate F and D struct format types (#149346) (
gh-121249: Deprecate using F/D type codes in the struct module (#152309)
vstinner commentedon Jun 30, 2026
@skirpichev: All PRs attached to this issues are merged. Can we close this issue?
skirpichev commentedon Jun 30, 2026
I think so :-)
Merge branch 'main' into maurycy/bye-abba