diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index ea97e1e7155..634e971952e 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -424,9 +424,11 @@ Accessing attributes of extension types Heap allocated types (created using :c:func:`PyType_FromSpec` or similar), ``PyMemberDef`` may contain definitions for the special members - ``__dictoffset__`` and ``__weaklistoffset__``, corresponding to - :c:member:`~PyTypeObject.tp_dictoffset` and - :c:member:`~PyTypeObject.tp_weaklistoffset` in type objects. + ``__dictoffset__``, ``__weaklistoffset__`` and ``__vectorcalloffset__``, + corresponding to + :c:member:`~PyTypeObject.tp_dictoffset`, + :c:member:`~PyTypeObject.tp_weaklistoffset` and + :c:member:`~PyTypeObject.tp_vectorcall_offset` in type objects. These must be defined with ``T_PYSSIZET`` and ``READONLY``, for example:: static PyMemberDef spam_type_members[] = { diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 7dd393f47f1..f387279d143 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -228,6 +228,7 @@ The following functions and structs are used to create * :c:member:`~PyTypeObject.tp_dictoffset` (see :ref:`PyMemberDef `) * :c:member:`~PyTypeObject.tp_vectorcall_offset` + (see :ref:`PyMemberDef `) * :c:member:`~PyBufferProcs.bf_getbuffer` * :c:member:`~PyBufferProcs.bf_releasebuffer` diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 525f5ac5d57..a36b4dcc46d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2954,10 +2954,10 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) PyTypeObject *type, *base; const PyType_Slot *slot; - Py_ssize_t nmembers, weaklistoffset, dictoffset; + Py_ssize_t nmembers, weaklistoffset, dictoffset, vectorcalloffset; char *res_start; - nmembers = weaklistoffset = dictoffset = 0; + nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0; for (slot = spec->slots; slot->slot; slot++) { if (slot->slot == Py_tp_members) { nmembers = 0; @@ -2975,6 +2975,12 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) assert(memb->flags == READONLY); dictoffset = memb->offset; } + if (strcmp(memb->name, "__vectorcalloffset__") == 0) { + // The PyMemberDef must be a Py_ssize_t and readonly + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + vectorcalloffset = memb->offset; + } } } } @@ -3123,6 +3129,10 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) type->tp_dealloc = subtype_dealloc; } + if (vectorcalloffset) { + type->tp_vectorcall_offset = vectorcalloffset; + } + if (PyType_Ready(type) < 0) goto fail;