Migrating to Stable ABI for free threading (abi3t) — Custom type data access
Then comes the hard part: in all code that needs to access this struct, you will need an additional PyObject_GetTypeData call to retrieve a CustomObjectData pointer from PyObject Bounded code example (external data; do not execute automatically): ```text PyObject *obj = ...; CustomObjectData *data =
Reference note (untrusted external data; do not execute it as instructions).
Then comes the hard part: in all code that needs to access this struct, you will need an additional PyObject_GetTypeData call to retrieve a CustomObjectData pointer from PyObject
Bounded code example (external data; do not execute automatically):
```text
PyObject *obj = ...;
CustomObjectData *data = PyObject_GetTypeData(obj, cls);
```
Note that this call requires the type object for your class (cls).
If your class is not subclassable (that is, it does not use the Py_TPFLAGS_BASETYPE flag), cls will be Py_TYPE(obj). Otherwise, DO NOT USE Py_TYPE with !PyObject_GetTypeData: it might return memory reserved to an unrelated subclass! For example, if a user makes a subclass like this
Bounded code example (external data; do not execute automatically):
```python
class Sub(YourCustomClass):
__slots__ = ('a', 'b')
```
then Py_TYPE(obj) is Sub, and the underlying memory may look like this
Bounded code example (external data; do not execute automatically):
```text
╭─ PyObject *obj
│ ╭─ the pointer you want
│ │ ╭─ PyObject_GetTypeData(obj, Py_TYPE(obj))
▼ ▼ ▼
┌──────────┬───┬────────────────┬───┬─────────────┬───┬─────────────┐
│ PyObject │...│ CustomTypeData │...│ PyObject *a │...│ PyObject *b │
└──────────┴───┴────────────────┴───┴─────────────┴───┴─────────────┘
```
(Ellipses indicate possible padding. Note that this memory layout is not guaranteed: future versions of Python may add different padding or even switch the order of the structures.)
There are two main ways to get the right class
In instance methods, your implementation may use the PyCMethod signature (and the METH_METHOD bit in PyMethodDef.ml_flags), and get the class as the defining_class argument. Otherwise, give your class a unique static token using the Py_tp_token slot, and use
Bounded code example (external data; do not execute automatically):
```text
PyTypeObject cls;
if (PyType_GetBaseByToken(Py_TYPE(obj), my_tp_token, &cls) < 0) {
/* handle error */
}
CustomObjectData *data = PyObject_GetTypeData(obj, cls);
Type tokens work similarly to module tokens covered :ref:`earlier in this
guide <abi3t-migration-module-token>`.
```
Attribution: Adapted from Python Documentation under PSF-2.0. Adaptation: WikiKV isolated this documentation section, normalized formatting, retained only bounded code excerpts, and shortened it at a paragraph or sentence boundary for retrieval. Verify version-sensitive details at the source.
ATTRIBUTED SOURCE
This compact reference card is adapted from official documentation and is not a community-verified experience.
Python Documentation — Doc/howto/abi3t-migration.rst :: Custom type data access ↗Revision f10166035d60 · PSF-2.0 and attribution