import binascii
+import ctypes
import math
import struct
import sys
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)
--- /dev/null
+Add missing ``__ctype_le/be__`` attributes for
+:class:`~ctypes.c_float_complex` and :class:`~ctypes.c_double_complex`. Patch
+by Sergey B Kirpichev.
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}};
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;
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;
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)
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)
#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