]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-41073: PyType_GetSlot() can now accept static types. (GH-21931)
authorHai Shi <shihai1992@gmail.com>
Tue, 10 Nov 2020 20:53:46 +0000 (04:53 +0800)
committerGitHub <noreply@github.com>
Tue, 10 Nov 2020 20:53:46 +0000 (12:53 -0800)
PyType_GetSlot() can now accept static types.

Co-Authored-By: Petr Viktorin <encukou@gmail.com>
Automerge-Triggered-By: GH:encukou
Doc/c-api/type.rst
Doc/whatsnew/3.10.rst
Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Objects/typeobject.c
Objects/typeslots.inc
Objects/typeslots.py

index fcd92e38e2428e2834743cc145d7c84cf3eb751f..f9037c89d8bd3b7cf20cd080e67eeb46d78ffdf3 100644 (file)
@@ -105,10 +105,12 @@ Type Objects
 
    See :c:member:`PyType_Slot.slot` for possible values of the *slot* argument.
 
-   An exception is raised if *type* is not a heap type.
-
    .. versionadded:: 3.4
 
+   .. versionchanged:: 3.10
+      :c:func:`PyType_GetSlot` can now accept all types.
+      Previously, it was limited to heap types.
+
 .. c:function:: PyObject* PyType_GetModule(PyTypeObject *type)
 
    Return the module object associated with the given type when the type was
index 76e11f0ddf0c068ef338ca6f020d3b92072d068c..807e87f2eef1182d01222994c526f648de4af8b5 100644 (file)
@@ -436,6 +436,9 @@ New Features
   slot.
   (Contributed by Hai Shi in :issue:`41832`.)
 
+* The :c:func:`PyType_GetSlot` function can accept static types.
+  (Contributed by Hai Shi and Petr Viktorin in :issue:`41073`.)
+
 
 Porting to Python 3.10
 ----------------------
diff --git a/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst b/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst
new file mode 100644 (file)
index 0000000..1bec2f1
--- /dev/null
@@ -0,0 +1 @@
+:c:func:`PyType_GetSlot()` can now accept static types.
index 4382b642dca7fb040dad53c7fca41156e438eab1..7b6da1e4c905590c8b4b9aeaedc403c415e0406e 100644 (file)
@@ -1018,6 +1018,62 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored))
 }
 
 
+static PyObject *
+test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new);
+    if (PyLong_Type.tp_new != tp_new) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: tp_new of long");
+        return NULL;
+    }
+
+    reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr);
+    if (PyLong_Type.tp_repr != tp_repr) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: tp_repr of long");
+        return NULL;
+    }
+
+    ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call);
+    if (tp_call != NULL) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: tp_call of long");
+        return NULL;
+    }
+
+    binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_nb_add);
+    if (PyLong_Type.tp_as_number->nb_add != nb_add) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: nb_add of long");
+        return NULL;
+    }
+
+    lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length);
+    if (mp_length != NULL) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: mp_length of long");
+        return NULL;
+    }
+
+    void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1);
+    if (over_value != NULL) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: max+1 of long");
+        return NULL;
+    }
+
+    tp_new = PyType_GetSlot(&PyLong_Type, 0);
+    if (tp_new != NULL) {
+        PyErr_SetString(PyExc_AssertionError, "mismatch: slot 0 of long");
+        return NULL;
+    }
+    if (PyErr_ExceptionMatches(PyExc_SystemError)) {
+        // This is the right exception
+        PyErr_Clear();
+    }
+    else {
+        return NULL;
+    }
+
+    Py_RETURN_NONE;
+}
+
+
 static PyObject *
 get_args(PyObject *self, PyObject *args)
 {
@@ -5627,8 +5683,10 @@ static PyMethodDef TestMethods[] = {
     {"PyBuffer_SizeFromFormat",  test_PyBuffer_SizeFromFormat, METH_VARARGS},
     {"test_buildvalue_N",       test_buildvalue_N,               METH_NOARGS},
     {"test_buildvalue_issue38913", test_buildvalue_issue38913,   METH_NOARGS},
-    {"get_args", get_args, METH_VARARGS},
-    {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS},
+    {"get_args",                get_args,                        METH_VARARGS},
+    {"test_get_statictype_slots", test_get_statictype_slots,     METH_NOARGS},
+    {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs,
+      METH_VARARGS|METH_KEYWORDS},
     {"getargs_tuple",           getargs_tuple,                   METH_VARARGS},
     {"getargs_keywords", (PyCFunction)(void(*)(void))getargs_keywords,
       METH_VARARGS|METH_KEYWORDS},
index b4188b8bcaf045829cbb19096dbaa71e417cd9cb..4d0a3faeceb89d7e1b658833ce0caf896301438f 100644 (file)
@@ -56,6 +56,11 @@ static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
 static unsigned int next_version_tag = 0;
 #endif
 
+typedef struct PySlot_Offset {
+    short subslot_offset;
+    short slot_offset;
+} PySlot_Offset;
+
 #define MCACHE_STATS 0
 
 #if MCACHE_STATS
@@ -2870,8 +2875,18 @@ error:
     return NULL;
 }
 
-static const short slotoffsets[] = {
-    -1, /* invalid slot */
+/* An array of type slot offsets corresponding to Py_tp_* constants,
+  * for use in e.g. PyType_Spec and PyType_GetSlot.
+  * Each entry has two offsets: "slot_offset" and "subslot_offset".
+  * If is subslot_offset is -1, slot_offset is an offset within the
+  * PyTypeObject struct.
+  * Otherwise slot_offset is an offset to a pointer to a sub-slots struct
+  * (such as "tp_as_number"), and subslot_offset is the offset within
+  * that struct.
+  * The actual table is generated by a script.
+  */
+static const PySlot_Offset pyslot_offsets[] = {
+    {0, 0},
 #include "typeslots.inc"
 };
 
@@ -2892,6 +2907,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
     const PyType_Slot *slot;
     Py_ssize_t nmembers, weaklistoffset, dictoffset, vectorcalloffset;
     char *res_start;
+    short slot_offset, subslot_offset;
 
     nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0;
     for (slot = spec->slots; slot->slot; slot++) {
@@ -3001,7 +3017,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
 
     for (slot = spec->slots; slot->slot; slot++) {
         if (slot->slot < 0
-            || (size_t)slot->slot >= Py_ARRAY_LENGTH(slotoffsets)) {
+            || (size_t)slot->slot >= Py_ARRAY_LENGTH(pyslot_offsets)) {
             PyErr_SetString(PyExc_RuntimeError, "invalid slot offset");
             goto fail;
         }
@@ -3034,7 +3050,15 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
         }
         else {
             /* Copy other slots directly */
-            *(void**)(res_start + slotoffsets[slot->slot]) = slot->pfunc;
+            PySlot_Offset slotoffsets = pyslot_offsets[slot->slot];
+            slot_offset = slotoffsets.slot_offset;
+            if (slotoffsets.subslot_offset == -1) {
+                *(void**)((char*)res_start + slot_offset) = slot->pfunc;
+            } else {
+                void *parent_slot = *(void**)((char*)res_start + slot_offset);
+                subslot_offset = slotoffsets.subslot_offset;
+                *(void**)((char*)parent_slot + subslot_offset) = slot->pfunc;
+            }
         }
     }
     if (type->tp_dealloc == NULL) {
@@ -3117,15 +3141,23 @@ PyType_FromSpec(PyType_Spec *spec)
 void *
 PyType_GetSlot(PyTypeObject *type, int slot)
 {
-    if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) {
+    void *parent_slot;
+    int slots_len = Py_ARRAY_LENGTH(pyslot_offsets);
+
+    if (slot <= 0 || slot >= slots_len) {
         PyErr_BadInternalCall();
         return NULL;
     }
-    if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) {
-        /* Extension module requesting slot from a future version */
+
+    parent_slot = *(void**)((char*)type + pyslot_offsets[slot].slot_offset);
+    if (parent_slot == NULL) {
         return NULL;
     }
-    return  *(void**)(((char*)type) + slotoffsets[slot]);
+    /* Return slot directly if we have no sub slot. */
+    if (pyslot_offsets[slot].subslot_offset == -1) {
+        return parent_slot;
+    }
+    return *(void**)((char*)parent_slot + pyslot_offsets[slot].subslot_offset);
 }
 
 PyObject *
index cc4ef1170fd28e7d0cf0f811fc1c2ae0fb29e668..896daa7d8066b765f18b1c39b238c4a0087a294a 100644 (file)
@@ -1,82 +1,82 @@
 /* Generated by typeslots.py */
-offsetof(PyHeapTypeObject, as_buffer.bf_getbuffer),
-offsetof(PyHeapTypeObject, as_buffer.bf_releasebuffer),
-offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript),
-offsetof(PyHeapTypeObject, as_mapping.mp_length),
-offsetof(PyHeapTypeObject, as_mapping.mp_subscript),
-offsetof(PyHeapTypeObject, as_number.nb_absolute),
-offsetof(PyHeapTypeObject, as_number.nb_add),
-offsetof(PyHeapTypeObject, as_number.nb_and),
-offsetof(PyHeapTypeObject, as_number.nb_bool),
-offsetof(PyHeapTypeObject, as_number.nb_divmod),
-offsetof(PyHeapTypeObject, as_number.nb_float),
-offsetof(PyHeapTypeObject, as_number.nb_floor_divide),
-offsetof(PyHeapTypeObject, as_number.nb_index),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_add),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_and),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_floor_divide),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_lshift),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_multiply),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_or),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_power),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_remainder),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_rshift),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_subtract),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_true_divide),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_xor),
-offsetof(PyHeapTypeObject, as_number.nb_int),
-offsetof(PyHeapTypeObject, as_number.nb_invert),
-offsetof(PyHeapTypeObject, as_number.nb_lshift),
-offsetof(PyHeapTypeObject, as_number.nb_multiply),
-offsetof(PyHeapTypeObject, as_number.nb_negative),
-offsetof(PyHeapTypeObject, as_number.nb_or),
-offsetof(PyHeapTypeObject, as_number.nb_positive),
-offsetof(PyHeapTypeObject, as_number.nb_power),
-offsetof(PyHeapTypeObject, as_number.nb_remainder),
-offsetof(PyHeapTypeObject, as_number.nb_rshift),
-offsetof(PyHeapTypeObject, as_number.nb_subtract),
-offsetof(PyHeapTypeObject, as_number.nb_true_divide),
-offsetof(PyHeapTypeObject, as_number.nb_xor),
-offsetof(PyHeapTypeObject, as_sequence.sq_ass_item),
-offsetof(PyHeapTypeObject, as_sequence.sq_concat),
-offsetof(PyHeapTypeObject, as_sequence.sq_contains),
-offsetof(PyHeapTypeObject, as_sequence.sq_inplace_concat),
-offsetof(PyHeapTypeObject, as_sequence.sq_inplace_repeat),
-offsetof(PyHeapTypeObject, as_sequence.sq_item),
-offsetof(PyHeapTypeObject, as_sequence.sq_length),
-offsetof(PyHeapTypeObject, as_sequence.sq_repeat),
-offsetof(PyHeapTypeObject, ht_type.tp_alloc),
-offsetof(PyHeapTypeObject, ht_type.tp_base),
-offsetof(PyHeapTypeObject, ht_type.tp_bases),
-offsetof(PyHeapTypeObject, ht_type.tp_call),
-offsetof(PyHeapTypeObject, ht_type.tp_clear),
-offsetof(PyHeapTypeObject, ht_type.tp_dealloc),
-offsetof(PyHeapTypeObject, ht_type.tp_del),
-offsetof(PyHeapTypeObject, ht_type.tp_descr_get),
-offsetof(PyHeapTypeObject, ht_type.tp_descr_set),
-offsetof(PyHeapTypeObject, ht_type.tp_doc),
-offsetof(PyHeapTypeObject, ht_type.tp_getattr),
-offsetof(PyHeapTypeObject, ht_type.tp_getattro),
-offsetof(PyHeapTypeObject, ht_type.tp_hash),
-offsetof(PyHeapTypeObject, ht_type.tp_init),
-offsetof(PyHeapTypeObject, ht_type.tp_is_gc),
-offsetof(PyHeapTypeObject, ht_type.tp_iter),
-offsetof(PyHeapTypeObject, ht_type.tp_iternext),
-offsetof(PyHeapTypeObject, ht_type.tp_methods),
-offsetof(PyHeapTypeObject, ht_type.tp_new),
-offsetof(PyHeapTypeObject, ht_type.tp_repr),
-offsetof(PyHeapTypeObject, ht_type.tp_richcompare),
-offsetof(PyHeapTypeObject, ht_type.tp_setattr),
-offsetof(PyHeapTypeObject, ht_type.tp_setattro),
-offsetof(PyHeapTypeObject, ht_type.tp_str),
-offsetof(PyHeapTypeObject, ht_type.tp_traverse),
-offsetof(PyHeapTypeObject, ht_type.tp_members),
-offsetof(PyHeapTypeObject, ht_type.tp_getset),
-offsetof(PyHeapTypeObject, ht_type.tp_free),
-offsetof(PyHeapTypeObject, as_number.nb_matrix_multiply),
-offsetof(PyHeapTypeObject, as_number.nb_inplace_matrix_multiply),
-offsetof(PyHeapTypeObject, as_async.am_await),
-offsetof(PyHeapTypeObject, as_async.am_aiter),
-offsetof(PyHeapTypeObject, as_async.am_anext),
-offsetof(PyHeapTypeObject, ht_type.tp_finalize),
-offsetof(PyHeapTypeObject, as_async.am_send),
+{offsetof(PyBufferProcs, bf_getbuffer), offsetof(PyTypeObject, tp_as_buffer)},
+{offsetof(PyBufferProcs, bf_releasebuffer), offsetof(PyTypeObject, tp_as_buffer)},
+{offsetof(PyMappingMethods, mp_ass_subscript), offsetof(PyTypeObject, tp_as_mapping)},
+{offsetof(PyMappingMethods, mp_length), offsetof(PyTypeObject, tp_as_mapping)},
+{offsetof(PyMappingMethods, mp_subscript), offsetof(PyTypeObject, tp_as_mapping)},
+{offsetof(PyNumberMethods, nb_absolute), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_add), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_and), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_bool), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_divmod), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_float), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_floor_divide), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_index), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_add), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_and), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_floor_divide), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_lshift), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_multiply), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_or), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_power), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_remainder), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_rshift), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_subtract), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_true_divide), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_xor), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_int), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_invert), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_lshift), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_multiply), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_negative), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_or), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_positive), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_power), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_remainder), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_rshift), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_subtract), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_true_divide), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_xor), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PySequenceMethods, sq_ass_item), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_concat), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_contains), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_inplace_concat), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_inplace_repeat), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_item), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_length), offsetof(PyTypeObject, tp_as_sequence)},
+{offsetof(PySequenceMethods, sq_repeat), offsetof(PyTypeObject, tp_as_sequence)},
+{-1, offsetof(PyTypeObject, tp_alloc)},
+{-1, offsetof(PyTypeObject, tp_base)},
+{-1, offsetof(PyTypeObject, tp_bases)},
+{-1, offsetof(PyTypeObject, tp_call)},
+{-1, offsetof(PyTypeObject, tp_clear)},
+{-1, offsetof(PyTypeObject, tp_dealloc)},
+{-1, offsetof(PyTypeObject, tp_del)},
+{-1, offsetof(PyTypeObject, tp_descr_get)},
+{-1, offsetof(PyTypeObject, tp_descr_set)},
+{-1, offsetof(PyTypeObject, tp_doc)},
+{-1, offsetof(PyTypeObject, tp_getattr)},
+{-1, offsetof(PyTypeObject, tp_getattro)},
+{-1, offsetof(PyTypeObject, tp_hash)},
+{-1, offsetof(PyTypeObject, tp_init)},
+{-1, offsetof(PyTypeObject, tp_is_gc)},
+{-1, offsetof(PyTypeObject, tp_iter)},
+{-1, offsetof(PyTypeObject, tp_iternext)},
+{-1, offsetof(PyTypeObject, tp_methods)},
+{-1, offsetof(PyTypeObject, tp_new)},
+{-1, offsetof(PyTypeObject, tp_repr)},
+{-1, offsetof(PyTypeObject, tp_richcompare)},
+{-1, offsetof(PyTypeObject, tp_setattr)},
+{-1, offsetof(PyTypeObject, tp_setattro)},
+{-1, offsetof(PyTypeObject, tp_str)},
+{-1, offsetof(PyTypeObject, tp_traverse)},
+{-1, offsetof(PyTypeObject, tp_members)},
+{-1, offsetof(PyTypeObject, tp_getset)},
+{-1, offsetof(PyTypeObject, tp_free)},
+{offsetof(PyNumberMethods, nb_matrix_multiply), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyNumberMethods, nb_inplace_matrix_multiply), offsetof(PyTypeObject, tp_as_number)},
+{offsetof(PyAsyncMethods, am_await), offsetof(PyTypeObject, tp_as_async)},
+{offsetof(PyAsyncMethods, am_aiter), offsetof(PyTypeObject, tp_as_async)},
+{offsetof(PyAsyncMethods, am_anext), offsetof(PyTypeObject, tp_as_async)},
+{-1, offsetof(PyTypeObject, tp_finalize)},
+{offsetof(PyAsyncMethods, am_send), offsetof(PyTypeObject, tp_as_async)},
index 9b6d4adbc7533b5abc00b0e41e0b78872d0560c3..8ab05f91be12b0db4249347c1264680a4d15e1f1 100755 (executable)
@@ -3,6 +3,7 @@
 
 import sys, re
 
+
 def generate_typeslots(out=sys.stdout):
     out.write("/* Generated by typeslots.py */\n")
     res = {}
@@ -10,27 +11,34 @@ def generate_typeslots(out=sys.stdout):
         m = re.match("#define Py_([a-z_]+) ([0-9]+)", line)
         if not m:
             continue
+
         member = m.group(1)
         if member.startswith("tp_"):
-            member = "ht_type."+member
+            member = f'{{-1, offsetof(PyTypeObject, {member})}}'
         elif member.startswith("am_"):
-            member = "as_async."+member
+            member = (f'{{offsetof(PyAsyncMethods, {member}),'+
+                      ' offsetof(PyTypeObject, tp_as_async)}')
         elif member.startswith("nb_"):
-            member = "as_number."+member
+            member = (f'{{offsetof(PyNumberMethods, {member}),'+
+                      ' offsetof(PyTypeObject, tp_as_number)}')
         elif member.startswith("mp_"):
-            member = "as_mapping."+member
+            member = (f'{{offsetof(PyMappingMethods, {member}),'+
+                      ' offsetof(PyTypeObject, tp_as_mapping)}')
         elif member.startswith("sq_"):
-            member = "as_sequence."+member
+            member = (f'{{offsetof(PySequenceMethods, {member}),'+
+                      ' offsetof(PyTypeObject, tp_as_sequence)}')
         elif member.startswith("bf_"):
-            member = "as_buffer."+member
+            member = (f'{{offsetof(PyBufferProcs, {member}),'+
+                      ' offsetof(PyTypeObject, tp_as_buffer)}')
         res[int(m.group(2))] = member
 
     M = max(res.keys())+1
     for i in range(1,M):
         if i in res:
-            out.write("offsetof(PyHeapTypeObject, %s),\n" % res[i])
+            out.write("%s,\n" % res[i])
         else:
-            out.write("0,\n")
+            out.write("{0, 0},\n")
+
 
 def main():
     if len(sys.argv) == 2: