| .. 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* -- essentally, 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 stuctures 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 |