import ctypes
import unittest
-from ctypes import Structure, POINTER, pointer, c_char_p
+from ctypes import Structure, POINTER, pointer, c_char_p, c_int
# String-based "incomplete pointers" were implemented in ctypes 0.6.3 (2003, when
# ctypes was an external project). They made obsolete by the current
lpcell.set_type(cell)
self.assertIs(POINTER(cell), lpcell)
+ def test_set_type_updates_format(self):
+ # gh-142966: set_type should update StgInfo.format
+ # to match the element type's format
+ with self.assertWarns(DeprecationWarning):
+ lp = POINTER("node")
+
+ class node(Structure):
+ _fields_ = [("value", c_int)]
+
+ # Get the expected format before set_type
+ node_format = memoryview(node()).format
+ expected_format = "&" + node_format
+
+ lp.set_type(node)
+
+ # Create instance to check format via memoryview
+ n = node(42)
+ p = lp(n)
+ actual_format = memoryview(p).format
+
+ # After set_type, the pointer's format should be "&<element_format>"
+ self.assertEqual(actual_format, expected_format)
+
if __name__ == '__main__':
unittest.main()
return -1;
}
Py_XSETREF(stginfo->proto, Py_NewRef(proto));
+
+ // Set the format string for the pointer type based on element type.
+ // If info->format is NULL, this is a pointer to an incomplete type.
+ // We create a generic format string 'pointer to bytes' in this case.
+ char *new_format = NULL;
STGINFO_LOCK(info);
if (info->pointer_type == NULL) {
Py_XSETREF(info->pointer_type, Py_NewRef(self));
}
+ const char *current_format = info->format ? info->format : "B";
+ if (info->shape != NULL) {
+ // pointer to an array: the shape needs to be prefixed
+ new_format = _ctypes_alloc_format_string_with_shape(
+ info->ndim, info->shape, "&", current_format);
+ } else {
+ new_format = _ctypes_alloc_format_string("&", current_format);
+ }
+ PyMem_Free(stginfo->format);
+ stginfo->format = new_format;
STGINFO_UNLOCK();
+
+ if (new_format == NULL) {
+ return -1;
+ }
return 0;
}
return -1;
}
if (proto) {
- const char *current_format;
if (PyCPointerType_SetProto(st, self, stginfo, proto) < 0) {
Py_DECREF(proto);
return -1;
}
- StgInfo *iteminfo;
- if (PyStgInfo_FromType(st, proto, &iteminfo) < 0) {
- Py_DECREF(proto);
- return -1;
- }
- /* PyCPointerType_SetProto has verified proto has a stginfo. */
- assert(iteminfo);
- /* If iteminfo->format is NULL, then this is a pointer to an
- incomplete type. We create a generic format string
- 'pointer to bytes' in this case. XXX Better would be to
- fix the format string later...
- */
- current_format = iteminfo->format ? iteminfo->format : "B";
- if (iteminfo->shape != NULL) {
- /* pointer to an array: the shape needs to be prefixed */
- stginfo->format = _ctypes_alloc_format_string_with_shape(
- iteminfo->ndim, iteminfo->shape, "&", current_format);
- } else {
- stginfo->format = _ctypes_alloc_format_string("&", current_format);
- }
Py_DECREF(proto);
- if (stginfo->format == NULL) {
- return -1;
- }
}
return 0;