@@ -3201,25 +3201,39 @@ static PyMethodDef PyCData_methods[] = {
32013201 { NULL , NULL },
32023202};
32033203
3204- static PyType_Slot pycdata_slots [] = {
3205- {Py_tp_dealloc , PyCData_dealloc },
3206- {Py_tp_hash , PyObject_HashNotImplemented },
3207- {Py_tp_doc , PyDoc_STR ("XXX to be provided" )},
3208- {Py_tp_traverse , PyCData_traverse },
3209- {Py_tp_clear , PyCData_clear },
3210- {Py_tp_methods , PyCData_methods },
3211- {Py_tp_members , PyCData_members },
3212- {Py_bf_getbuffer , PyCData_NewGetBuffer },
3213- {0 , NULL },
3214- };
3215-
3216- static PyType_Spec pycdata_spec = {
3217- .name = "_ctypes._CData" ,
3218- .basicsize = sizeof (CDataObject ),
3219- .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
3220- Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION ),
3221- .slots = pycdata_slots ,
3222- };
3204+ /*
3205+ * CData objects are mutable, so they cannot be hashable. Setting tp_hash to
3206+ * PyObject_HashNotImplemented() makes type_ready() set __hash__ to None.
3207+ *
3208+ * Unfortunately, on Windows, PyObject_HashNotImplemented is imported from
3209+ * the Python DLL, and MSVC resolves the address of an imported function in
3210+ * a static initializer to a local thunk that can't be recognized. So, we
3211+ * initialize the slots at runtime to load the real address from the import table.
3212+ */
3213+ static PyObject *
3214+ PyCData_create_type (PyObject * mod )
3215+ {
3216+ PyType_Slot slots [] = {
3217+ {Py_tp_dealloc , PyCData_dealloc },
3218+ {Py_tp_hash , PyObject_HashNotImplemented },
3219+ {Py_tp_doc , PyDoc_STR ("XXX to be provided" )},
3220+ {Py_tp_traverse , PyCData_traverse },
3221+ {Py_tp_clear , PyCData_clear },
3222+ {Py_tp_methods , PyCData_methods },
3223+ {Py_tp_members , PyCData_members },
3224+ {Py_bf_getbuffer , PyCData_NewGetBuffer },
3225+ {0 , NULL },
3226+ };
3227+ PyType_Spec spec = {
3228+ .name = "_ctypes._CData" ,
3229+ .basicsize = sizeof (CDataObject ),
3230+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
3231+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE |
3232+ Py_TPFLAGS_DISALLOW_INSTANTIATION ),
3233+ .slots = slots ,
3234+ };
3235+ return PyType_FromMetaclass (NULL , mod , & spec , NULL );
3236+ }
32233237
32243238static int
32253239PyCData_MallocBuffer (CDataObject * obj , StgInfo * info )
@@ -6239,7 +6253,10 @@ _ctypes_add_types(PyObject *mod)
62396253 */
62406254 CREATE_TYPE (st -> PyCArg_Type , & carg_spec , NULL , NULL );
62416255 CREATE_TYPE (st -> PyCThunk_Type , & cthunk_spec , NULL , NULL );
6242- CREATE_TYPE (st -> PyCData_Type , & pycdata_spec , NULL , NULL );
6256+ st -> PyCData_Type = (PyTypeObject * )PyCData_create_type (mod );
6257+ if (st -> PyCData_Type == NULL ) {
6258+ return -1 ;
6259+ }
62436260
62446261 // Common Metaclass
62456262 CREATE_TYPE (st -> PyCType_Type , & pyctype_type_spec ,
0 commit comments