@@ -264,6 +264,24 @@ Type Objects
264
264
265
265
.. versionadded:: 3.11
266
266
267
+ .. c:function:: int PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result)
268
+
269
+ Find the first superclass in *type *'s :term: `method resolution order ` whose
270
+ :c:macro: `Py_tp_token ` token is equal to the given one.
271
+
272
+ * If found, set *\* result * to a new :term: `strong reference `
273
+ to it and return ``1 ``.
274
+ * If not found, set *\* result * to ``NULL `` and return ``0 ``.
275
+ * On error, set *\* result * to ``NULL `` and return ``-1 `` with an
276
+ exception set.
277
+
278
+ The *result * argument may be ``NULL ``, in which case *\* result * is not set.
279
+ Use this if you need only the return value.
280
+
281
+ The *token * argument may not be ``NULL ``.
282
+
283
+ .. versionadded :: 3.14
284
+
267
285
.. c :function :: int PyUnstable_Type_AssignVersionTag (PyTypeObject *type)
268
286
269
287
Attempt to assign a version tag to the given type.
@@ -488,6 +506,11 @@ The following functions and structs are used to create
488
506
* ``Py_nb_add `` to set :c:member: `PyNumberMethods.nb_add `
489
507
* ``Py_sq_length `` to set :c:member: `PySequenceMethods.sq_length `
490
508
509
+ An additional slot is supported that does not correspond to a
510
+ :c:type: `!PyTypeObject ` struct field:
511
+
512
+ * :c:data: `Py_tp_token `
513
+
491
514
The following “offset” fields cannot be set using :c:type: `PyType_Slot `:
492
515
493
516
* :c:member: `~PyTypeObject.tp_weaklistoffset `
@@ -538,4 +561,47 @@ The following functions and structs are used to create
538
561
The desired value of the slot. In most cases, this is a pointer
539
562
to a function.
540
563
541
- Slots other than ``Py_tp_doc`` may not be ``NULL``.
564
+ *pfunc* values may not be ``NULL``, except for the following slots:
565
+
566
+ * ``Py_tp_doc``
567
+ * :c:data:`Py_tp_token` (for clarity, prefer :c:data: `Py_TP_USE_SPEC `
568
+ rather than ``NULL ``)
569
+
570
+ .. c:macro:: Py_tp_token
571
+
572
+ A :c:member:`~PyType_Slot.slot` that records a static memory layout ID
573
+ for a class.
574
+
575
+ If the :c:type:`PyType_Spec` of the class is statically
576
+ allocated, the token can be set to the spec using the special value
577
+ :c:data:`Py_TP_USE_SPEC`:
578
+
579
+ .. code-block:: c
580
+
581
+ static PyType_Slot foo_slots[] = {
582
+ {Py_tp_token, Py_TP_USE_SPEC},
583
+
584
+ It can also be set to an arbitrary pointer, but you must ensure that:
585
+
586
+ * The pointer outlives the class, so it's not reused for something else
587
+ while the class exists.
588
+ * It "belongs" to the extension module where the class lives, so it will not
589
+ clash with other extensions.
590
+
591
+ Use :c:func: `PyType_GetBaseByToken ` to check if a class's superclass has
592
+ a given token -- that is, check whether the memory layout is compatible.
593
+
594
+ To get the token for a given class (without considering superclasses),
595
+ use :c:func: `PyType_GetSlot ` with ``Py_tp_token ``.
596
+
597
+ .. versionadded :: 3.14
598
+
599
+ .. c :namespace :: NULL
600
+
601
+ .. c :macro :: Py_TP_USE_SPEC
602
+
603
+ Used as a value with :c:data: `Py_tp_token ` to set the token to the
604
+ class's :c:type: `PyType_Spec `.
605
+ Expands to ``NULL ``.
606
+
607
+ .. versionadded :: 3.14
0 commit comments