I want to put a frozenset into itself and to put a tuple into itself.
It seems easy. By writing a simple c++ extension, I was capable to output this:
frozenset({frozenset(...)})
((...),)
... means that object is inside itself
Is it possbile to do the same using just python and it's standard library?
This is indeed possible with ctypes, Note that this code only works properly on 64-bit systems, as it assumes that ssize_t
and pointers are the same size.
import ctypes
x = (0, )
(ctypes.c_void_p * 4).from_address(id(x))[3] = ctypes.cast(id(x), ctypes.c_void_p)
print(x)
# ((...),)
typedef struct {
PyObject_VAR_HEAD
/* ob_item contains space for 'ob_size' elements.
Items must normally not be NULL, except during construction when
the tuple is not yet visible outside the function that builds it. */
PyObject *ob_item[1];
} PyTupleObject;
( https://github.com/python/cpython/blob/main/Include/cpython/tupleobject.h )
This is the struct definition for tuple objects, straight from the CPython source. Our goal is to override the first element of ob_item
with a pointer to the tuple itself.
#define PyObject_VAR_HEAD PyVarObject ob_base;
// ...
struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;
};
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
( https://github.com/python/cpython/blob/main/Include/object.h )
We can see that a PyTupleObject
will contain the following 3 fields prior to the ob_item
array: ob_refcnt
(a ssize_t
), ob_type
(a pointer) and ob_size (another ssize_t
) ( _PyObject_HEAD_EXTRA
is only used in debug builds IIRC).
We can take the lazy way out and assume that ssize_t
and pointers are the same size (which works for 64-bit systems), which lets us treat the PyTupleObject
as an array of void pointers.
Finally, we change the 4th pointer in this array (which will be the pointer to the first element of the tuple) to point to the address of the tuple itself (which we get via the CPython-specific implementation detail of id
returning the address of an object).
A proper solution would involve creating custom ctypes.Structure
classes to represent the structs instead of an system-specific array hack.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.