I have a custom implementation of dict using a C extension. All works but the pickling of views and iter types. Python segfaults if I try to pickle them.
For example, I have: static PyTypeObject PyFrozenDictIterKey_Type = { PyVarObject_HEAD_INIT(NULL, 0) "frozendict.keyiterator", /* tp_name */ sizeof(dictiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ PyObject_HashNotImplemented, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)frozendictiter_iternextkey, /* tp_iternext */ dictiter_methods, /* tp_methods */ 0, }; This is the backtrace I get with gdb: #0 PyObject_Hash (v=0x7f043ce15540 <PyFrozenDictIterKey_Type>) at ../cpython_3_10/Objects/object.c:788 #1 0x000000000048611c in PyDict_GetItemWithError (op=0x7f043e1f4900, key=key@entry=0x7f043ce15540 <PyFrozenDictIterKey_Type>) at ../cpython_3_10/Objects/dictobject.c:1520 #2 0x00007f043ce227f6 in save (self=self@entry=0x7f043d8507d0, obj=obj@entry=0x7f043e1fb0b0, pers_save=pers_save@entry=0) at /home/marco/sources/cpython_3_10/Modules/_pickle.c:4381 #3 0x00007f043ce2534d in dump (self=self@entry=0x7f043d8507d0, obj=obj@entry=0x7f043e1fb0b0) at /home/marco/sources/cpython_3_10/Modules/_pickle.c:4515 #4 0x00007f043ce2567f in _pickle_dumps_impl (module=<optimized out>, buffer_callback=<optimized out>, fix_imports=<optimized out>, protocol=<optimized out>, obj=0x7f043e1fb0b0) at /home/marco/sources/cpython_3_10/Modules/_pickle.c:1203 #5 _pickle_dumps (module=<optimized out>, args=<optimized out>, nargs=<optimized out>, kwnames=<optimized out>) at /home/marco/sources/cpython_3_10/Modules/clinic/_pickle.c.h:619 and so on. The problematic part is in the second frame. Indeed the code of _pickle.c here is: reduce_func = PyDict_GetItemWithError(st->dispatch_table, (PyObject *)type); The problem is that type is NULL. It tries to get the attribute tp_hash and it segfaults. I tried to change the header of the type to: PyVarObject_HEAD_INIT(&PyType_Type, 0) This way it works but, as known, it does not compile on Windows. The strange fact is that pickling the main type works, even if the type is NULL, as suggested for a custom type. This is the main type: PyTypeObject PyFrozenDict_Type = { PyVarObject_HEAD_INIT(NULL, 0) "frozendict." FROZENDICT_CLASS_NAME, /* tp_name */ sizeof(PyFrozenDictObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)dict_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ (reprfunc)frozendict_repr, /* tp_repr */ &frozendict_as_number, /* tp_as_number */ &dict_as_sequence, /* tp_as_sequence */ &frozendict_as_mapping, /* tp_as_mapping */ (hashfunc)frozendict_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_MAPPING, /* tp_flags */ frozendict_doc, /* tp_doc */ dict_traverse, /* tp_traverse */ 0, /* tp_clear */ dict_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)frozendict_iter, /* tp_iter */ 0, /* tp_iternext */ frozendict_mapp_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ frozendict_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ .tp_vectorcall = frozendict_vectorcall, }; -- https://mail.python.org/mailman/listinfo/python-list