mirror of
https://github.com/python/cpython.git
synced 2026-05-06 04:37:33 -04:00
[3.14] gh-148464: Add missing `__ctype_le/be__` attributes for complex types in the ctype module (GH-148485) (GH-148677)
(cherry picked from commit 769cc8338f)
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
b6a7212edb
commit
5e758ff525
@@ -166,6 +166,48 @@ class Test(unittest.TestCase, StructCheckMixin):
|
||||
self.assertEqual(s.value, math.pi)
|
||||
self.assertEqual(bin(struct.pack(">d", math.pi)), bin(s))
|
||||
|
||||
@unittest.skipUnless(hasattr(ctypes, 'c_float_complex'), "No complex types")
|
||||
def test_endian_float_complex(self):
|
||||
c_float_complex = ctypes.c_float_complex
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_float_complex.__ctype_le__, c_float_complex)
|
||||
self.assertIs(c_float_complex.__ctype_be__.__ctype_le__,
|
||||
c_float_complex)
|
||||
else:
|
||||
self.assertIs(c_float_complex.__ctype_be__, c_float_complex)
|
||||
self.assertIs(c_float_complex.__ctype_le__.__ctype_be__,
|
||||
c_float_complex)
|
||||
s = c_float_complex(math.pi+1j)
|
||||
self.assertEqual(bin(struct.pack("F", math.pi+1j)), bin(s))
|
||||
self.assertAlmostEqual(s.value, math.pi+1j, places=6)
|
||||
s = c_float_complex.__ctype_le__(math.pi+1j)
|
||||
self.assertAlmostEqual(s.value, math.pi+1j, places=6)
|
||||
self.assertEqual(bin(struct.pack("<F", math.pi+1j)), bin(s))
|
||||
s = c_float_complex.__ctype_be__(math.pi+1j)
|
||||
self.assertAlmostEqual(s.value, math.pi+1j, places=6)
|
||||
self.assertEqual(bin(struct.pack(">F", math.pi+1j)), bin(s))
|
||||
|
||||
@unittest.skipUnless(hasattr(ctypes, 'c_double_complex'), "No complex types")
|
||||
def test_endian_double_complex(self):
|
||||
c_double_complex = ctypes.c_double_complex
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_double_complex.__ctype_le__, c_double_complex)
|
||||
self.assertIs(c_double_complex.__ctype_be__.__ctype_le__,
|
||||
c_double_complex)
|
||||
else:
|
||||
self.assertIs(c_double_complex.__ctype_be__, c_double_complex)
|
||||
self.assertIs(c_double_complex.__ctype_le__.__ctype_be__,
|
||||
c_double_complex)
|
||||
s = c_double_complex(math.pi+1j)
|
||||
self.assertEqual(bin(struct.pack("D", math.pi+1j)), bin(s))
|
||||
self.assertAlmostEqual(s.value, math.pi+1j, places=6)
|
||||
s = c_double_complex.__ctype_le__(math.pi+1j)
|
||||
self.assertAlmostEqual(s.value, math.pi+1j, places=6)
|
||||
self.assertEqual(bin(struct.pack("<D", math.pi+1j)), bin(s))
|
||||
s = c_double_complex.__ctype_be__(math.pi+1j)
|
||||
self.assertAlmostEqual(s.value, math.pi+1j, places=6)
|
||||
self.assertEqual(bin(struct.pack(">D", math.pi+1j)), bin(s))
|
||||
|
||||
def test_endian_other(self):
|
||||
self.assertIs(c_byte.__ctype_le__, c_byte)
|
||||
self.assertIs(c_byte.__ctype_be__, c_byte)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Add missing ``__ctype_le/be__`` attributes for
|
||||
:class:`~ctypes.c_float_complex` and :class:`~ctypes.c_double_complex`. Patch
|
||||
by Sergey B Kirpichev.
|
||||
+31
-14
@@ -2232,6 +2232,31 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
set_stginfo_ffi_type_pointer(StgInfo *stginfo, struct fielddesc *fmt)
|
||||
{
|
||||
if (!fmt->pffi_type->elements) {
|
||||
stginfo->ffi_type_pointer = *fmt->pffi_type;
|
||||
}
|
||||
else {
|
||||
/* From primitive types - only complex types have the elements
|
||||
struct field as non-NULL (two element array). */
|
||||
assert(fmt->pffi_type->type == FFI_TYPE_COMPLEX);
|
||||
const size_t els_size = 2 * sizeof(ffi_type *);
|
||||
stginfo->ffi_type_pointer.size = fmt->pffi_type->size;
|
||||
stginfo->ffi_type_pointer.alignment = fmt->pffi_type->alignment;
|
||||
stginfo->ffi_type_pointer.type = fmt->pffi_type->type;
|
||||
stginfo->ffi_type_pointer.elements = PyMem_Malloc(els_size);
|
||||
if (!stginfo->ffi_type_pointer.elements) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
memcpy(stginfo->ffi_type_pointer.elements,
|
||||
fmt->pffi_type->elements, els_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyMethodDef c_void_p_methods[] = {C_VOID_P_FROM_PARAM_METHODDEF {0}};
|
||||
static PyMethodDef c_char_p_methods[] = {C_CHAR_P_FROM_PARAM_METHODDEF {0}};
|
||||
static PyMethodDef c_wchar_p_methods[] = {C_WCHAR_P_FROM_PARAM_METHODDEF {0}};
|
||||
@@ -2276,8 +2301,10 @@ static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type,
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stginfo->ffi_type_pointer = *fmt->pffi_type;
|
||||
if (set_stginfo_ffi_type_pointer(stginfo, fmt)) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
stginfo->align = fmt->pffi_type->alignment;
|
||||
stginfo->length = 0;
|
||||
stginfo->size = fmt->pffi_type->size;
|
||||
@@ -2372,18 +2399,8 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
if (!stginfo) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!fmt->pffi_type->elements) {
|
||||
stginfo->ffi_type_pointer = *fmt->pffi_type;
|
||||
}
|
||||
else {
|
||||
const size_t els_size = sizeof(fmt->pffi_type->elements);
|
||||
stginfo->ffi_type_pointer.size = fmt->pffi_type->size;
|
||||
stginfo->ffi_type_pointer.alignment = fmt->pffi_type->alignment;
|
||||
stginfo->ffi_type_pointer.type = fmt->pffi_type->type;
|
||||
stginfo->ffi_type_pointer.elements = PyMem_Malloc(els_size);
|
||||
memcpy(stginfo->ffi_type_pointer.elements,
|
||||
fmt->pffi_type->elements, els_size);
|
||||
if (set_stginfo_ffi_type_pointer(stginfo, fmt)) {
|
||||
goto error;
|
||||
}
|
||||
stginfo->align = fmt->pffi_type->alignment;
|
||||
stginfo->length = 0;
|
||||
|
||||
@@ -792,6 +792,44 @@ D_get(void *ptr, Py_ssize_t size)
|
||||
return PyComplex_FromDoubles(x[0], x[1]);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
D_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||
{
|
||||
assert(NUM_BITS(size) || (size == 2*sizeof(double)));
|
||||
Py_complex c = PyComplex_AsCComplex(value);
|
||||
|
||||
if (c.real == -1 && PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (PyFloat_Pack8(c.real, ptr, 1)
|
||||
|| PyFloat_Pack8(c.imag, ptr + sizeof(double), 1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (PyFloat_Pack8(c.real, ptr, 0)
|
||||
|| PyFloat_Pack8(c.imag, ptr + sizeof(double), 0))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
_RET(value);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
D_get_sw(void *ptr, Py_ssize_t size)
|
||||
{
|
||||
assert(NUM_BITS(size) || (size == 2*sizeof(double)));
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return PyComplex_FromDoubles(PyFloat_Unpack8(ptr, 1),
|
||||
PyFloat_Unpack8(ptr + sizeof(double), 1));
|
||||
#else
|
||||
return PyComplex_FromDoubles(PyFloat_Unpack8(ptr, 0),
|
||||
PyFloat_Unpack8(ptr + sizeof(double), 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* F: float complex */
|
||||
static PyObject *
|
||||
F_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||
@@ -817,6 +855,44 @@ F_get(void *ptr, Py_ssize_t size)
|
||||
return PyComplex_FromDoubles(x[0], x[1]);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
F_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||
{
|
||||
assert(NUM_BITS(size) || (size == 2*sizeof(float)));
|
||||
Py_complex c = PyComplex_AsCComplex(value);
|
||||
|
||||
if (c.real == -1 && PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (PyFloat_Pack4(c.real, ptr, 1)
|
||||
|| PyFloat_Pack4(c.imag, ptr + sizeof(float), 1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (PyFloat_Pack4(c.real, ptr, 0)
|
||||
|| PyFloat_Pack4(c.imag, ptr + sizeof(float), 0))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
_RET(value);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
F_get_sw(void *ptr, Py_ssize_t size)
|
||||
{
|
||||
assert(NUM_BITS(size) || (size == 2*sizeof(float)));
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return PyComplex_FromDoubles(PyFloat_Unpack4(ptr, 1),
|
||||
PyFloat_Unpack4(ptr + sizeof(float), 1));
|
||||
#else
|
||||
return PyComplex_FromDoubles(PyFloat_Unpack4(ptr, 0),
|
||||
PyFloat_Unpack4(ptr + sizeof(float), 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* G: long double complex */
|
||||
static PyObject *
|
||||
G_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||
@@ -1602,7 +1678,9 @@ for base_code, base_c_type in [
|
||||
#if defined(_Py_FFI_SUPPORT_C_COMPLEX)
|
||||
if (Py_FFI_COMPLEX_AVAILABLE) {
|
||||
TABLE_ENTRY(D, &ffi_type_complex_double);
|
||||
TABLE_ENTRY_SW(D, &ffi_type_complex_double);
|
||||
TABLE_ENTRY(F, &ffi_type_complex_float);
|
||||
TABLE_ENTRY_SW(F, &ffi_type_complex_float);
|
||||
TABLE_ENTRY(G, &ffi_type_complex_longdouble);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user