| .. highlight:: c | |
| .. _capi-slots: | |
| Definition slots | |
| ================ | |
| To define :ref:`module objects <moduleobjects>` and | |
| :ref:`classes <creating-heap-types>` using the C API, you may use | |
| an array of *slots* -- essentially, key-value pairs that describe features | |
| of the object to create. | |
| This decouples the data from the structures used at runtime, allowing CPython | |
| -- and other Python C API implementations -- to update the structures without | |
| breaking backwards compatibility. | |
| This section documents slots in general. | |
| For object-specific behavior and slot values, see documentation for functions | |
| that apply slots: | |
| - :c:func:`PyType_FromSlots` for types; | |
| - :c:func:`PyModule_FromSlotsAndSpec` and :ref:`extension-export-hook` | |
| for modules. | |
| When slots are passed to a function that applies them, the function will | |
| not modify the slot array, nor any data it points to (recursively). | |
| After the function is done, the caller is allowed to modify or deallocate | |
| the array and any data it points to (recursively), except data | |
| explicitly marked with :c:macro:`PySlot_STATIC`. | |
| Except when documented otherwise, multiple slots with the same ID | |
| (:c:member:`~PySlot.sl_id`) may not occur in a single slots array. | |
| .. versionadded:: 3.15 | |
| Slot arrays generalize an earlier way of defining objects: | |
| using :c:type:`PyType_Spec` with :c:type:`PyType_Slot` for types, and | |
| :c:type:`PyModuleDef` with :c:type:`PyModuleDef_Slot` for modules. | |
| The earlier API is :term:`soft deprecated`; there are no plans to remove it. | |
| Entries of the slots array use the following structure: | |
| .. c:type:: PySlot | |
| An entry in a slots array. Defined as: | |
| .. code-block:: c | |
| typedef struct { | |
| uint16_t sl_id; | |
| uint16_t sl_flags; | |
| uint32_t _reserved; // must be 0 | |
| union { | |
| void *sl_ptr; | |
| void (*sl_func)(void); | |
| Py_ssize_t sl_size; | |
| int64_t sl_int64; | |
| uint64_t sl_uint64; | |
| }; | |
| } PySlot; | |
| .. c:member:: uint16_t sl_id | |
| A slot ID, chosen from: | |
| - ``Py_slot_*`` values documented in :ref:`pyslot-common-ids` below; | |
| - ``Py_mod_*`` values for modules, as documented in :ref:`c_module_slots`; | |
| - Values for types, as documented in :ref:`pyslot_type_slot_ids`. | |
| A :c:member:`!sl_id` of zero (:c:macro:`Py_slot_end`) marks the end of a | |
| slots array. | |
| .. c:member:: void *sl_ptr | |
| void (*sl_func)(void) | |
| Py_ssize_t sl_size | |
| int64_t sl_int64 | |
| uint64_t sl_uint64 | |
| The data for the slot. | |
| These members are part of an anonymous union; | |
| the member to use depends on which data type is required by the slot ID: | |
| data pointer, function pointer, size, signed or unsigned | |
| integer, respectively. | |
| Except when documented otherwise for a specific slot ID, pointers | |
| (that is :c:member:`!sl_ptr` and :c:member:`!sl_func`) may not be NULL. | |
| .. c:member:: uint16_t sl_flags | |
| Zero or more of the following flags, OR-ed together: | |
| .. c:namespace:: NULL | |
| .. c:macro:: PySlot_STATIC | |
| All data the slot points to is statically allocated and constant. | |
| Thus, the interpreter does not need to copy the information. | |
| This flag is implied for function pointers. | |
| The flag applies even to data the slot points to “indirectly”, | |
| except for slots nested via :c:macro:`Py_slot_subslots` which may | |
| have their own :c:macro:`!PySlot_STATIC` flags. | |
| For example, if applied to a :c:macro:`Py_tp_members` slot that | |
| points to an array of :c:type:`PyMemberDef` structures, | |
| then the entire array, as well as the name and doc strings | |
| in its elements, must be static and constant. | |
| .. c:macro:: PySlot_INTPTR | |
| The data is stored in ``sl_ptr``; CPython will cast it to | |
| the appropriate type. | |
| This flag can simplify porting from the older :c:type:`PyType_Slot` | |
| and :c:type:`PyModuleDef_Slot` structures. | |
| .. c:macro:: PySlot_OPTIONAL | |
| If the slot ID is unknown, the interpreter should ignore the | |
| slot, rather than fail. | |
| For example, if Python 3.16 adds a new feature with a new slot ID,attr | |
| the corresponding slot may be marked :c:macro:`!PySlot_OPTIONAL` | |
| so that Python 3.15 ignores it. | |
| Note that the "optionality" only applies to unknown slot IDs. | |
| This flag does not make Python skip invalid values of known slots. | |
| .. versionadded:: 3.15 | |
| Convenience macros | |
| ------------------ | |
| .. c:macro:: PySlot_DATA(name, value) | |
| PySlot_FUNC(name, value) | |
| PySlot_SIZE(name, value) | |
| PySlot_INT64(name, value) | |
| PySlot_UINT64(name, value) | |
| PySlot_STATIC_DATA(name, value) | |
| Convenience macros to define :c:type:`!PySlot` structures with | |
| :c:member:`~PySlot.sl_id` and a particular union member set. | |
| :c:macro:`!PySlot_STATIC_DATA` sets the :c:macro:`PySlot_STATIC` flag; | |
| others set no flags. | |
| Note that these macros use *designated initializers*, a C language feature | |
| that C++ added in the 2020 version of the standard. | |
| If your code needs to be compatible with C++11 or older, | |
| use :c:macro:`PySlot_PTR` instead. | |
| Defined as:: | |
| #define PySlot_DATA(NAME, VALUE) \ | |
| {.sl_id=NAME, .sl_ptr=(void*)(VALUE)} | |
| #define PySlot_FUNC(NAME, VALUE) \ | |
| {.sl_id=NAME, .sl_func=(VALUE)} | |
| #define PySlot_SIZE(NAME, VALUE) \ | |
| {.sl_id=NAME, .sl_size=(VALUE)} | |
| #define PySlot_INT64(NAME, VALUE) \ | |
| {.sl_id=NAME, .sl_int64=(VALUE)} | |
| #define PySlot_UINT64(NAME, VALUE) \ | |
| {.sl_id=NAME, .sl_uint64=(VALUE)} | |
| #define PySlot_STATIC_DATA(NAME, VALUE) \ | |
| {.sl_id=NAME, .sl_flags=PySlot_STATIC, .sl_ptr=(VALUE)} | |
| .. versionadded:: 3.15 | |
| .. c:macro:: PySlot_END | |
| Convenience macro to mark the end of a :c:type:`!PySlot` array. | |
| Defined as:: | |
| #define PySlot_END {0} | |
| .. versionadded:: 3.15 | |
| .. c:macro:: PySlot_PTR(name, value) | |
| PySlot_PTR_STATIC(name, value) | |
| Convenience macros for use in C++11-compatible code. | |
| This version of C++ does not allow setting arbitrary union members in | |
| literals; instead, these macros set the :c:macro:`PySlot_INTPTR` flag and cast | |
| the value to ``(void*)``. | |
| Defined as:: | |
| #define PySlot_PTR(NAME, VALUE) \ | |
| {NAME, PySlot_INTPTR, {0}, {(void*)(VALUE)}} | |
| #define PySlot_PTR_STATIC(NAME, VALUE) \ | |
| {NAME, PySlot_INTPTR|Py_SLOT_STATIC, {0}, {(void*)(VALUE)}} | |
| .. versionadded:: 3.15 | |
| .. _pyslot-common-ids: | |
| Common slot IDs | |
| --------------- | |
| The following slot IDs may be used in both type and module definitions. | |
| .. c:macro:: Py_slot_end | |
| Marks the end of a slots array. | |
| Defined as zero. | |
| .. versionadded:: 3.15 | |
| .. c:macro:: Py_slot_subslots | |
| Nested slots array. | |
| The value (:c:member:`~PySlot.sl_ptr`) should point to an array of | |
| :c:type:`PySlot` structures. | |
| The slots in the array (up to but not including the zero-ID | |
| terminator) will be treated as if they were inserted if the current | |
| slot array, at the point :c:macro:`!Py_slot_subslots` appears. | |
| Slot nesting depth is limited to 5 levels. | |
| This restriction may be lifted in the future. | |
| .. versionadded:: 3.15 | |
| .. c:macro:: Py_slot_invalid | |
| Reserved; will always be treated as an unknown slot ID. | |
| Defined as ``UINT16_MAX`` (``0xFFFF``). | |
| When used with the :c:macro:`PySlot_OPTIONAL` flag, defines a slot with | |
| no effect. | |
| Without the flag, processing a slot with this ID will fail. | |
| .. versionadded:: 3.15 |