11/* ------------------------------------------------------------------------- */
22
3- #ifndef Py_LIMITED_API
4- /* stable ABI Python >= 3.6, keep in sync with setup.cfg py_limited_api */
5- #define Py_LIMITED_API 0x03060000
6- #endif
7-
83#include "Python.h"
94
105#include "structmember.h"
138#define PyVarObject_HEAD_INIT (type , size ) PyObject_HEAD_INIT(type) size,
149#endif
1510
11+ /* Heap types in Python < 3.9 don't support __weaklistoffset__ and
12+ * __dictoffset__ in PyMemberDef.
13+ */
14+ #if PY_VERSION_HEX >= 0x03090000
15+ #define WRAPT_HEAPTYPE_SUPPORT_OFFSET 1
16+ #endif
17+
18+ /* Instanes of heap types in Python < 3.8 don't hold strong ref to their
19+ * type object.
20+ */
21+ #if PY_VERSION_HEX >= 0x03080000
22+ #define WRAPT_HEAPTYPE_STRONG_TYPEREF 1
23+ #endif
24+
1625/* ------------------------------------------------------------------------- */
1726
1827typedef struct {
@@ -147,6 +156,7 @@ static int WraptObjectProxy_init(WraptObjectProxyObject *self,
147156static int WraptObjectProxy_traverse (WraptObjectProxyObject * self ,
148157 visitproc visit , void * arg )
149158{
159+ Py_VISIT (Py_TYPE (self ));
150160 Py_VISIT (self -> dict );
151161 Py_VISIT (self -> wrapped );
152162
@@ -167,7 +177,10 @@ static int WraptObjectProxy_clear(WraptObjectProxyObject *self)
167177
168178static void WraptObjectProxy_dealloc (WraptObjectProxyObject * self )
169179{
180+ #ifdef WRAPT_HEAPTYPE_STRONG_TYPEREF
181+ /* Type decref causes segfaults in <= 3.7 */
170182 PyTypeObject * tp = Py_TYPE (self );
183+ #endif
171184
172185 PyObject_GC_UnTrack (self );
173186
@@ -179,7 +192,9 @@ static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self)
179192 freefunc free_func = PyType_GetSlot (Py_TYPE (self ), Py_tp_free );
180193 free_func (self );
181194
195+ #ifdef WRAPT_HEAPTYPE_STRONG_TYPEREF
182196 Py_DECREF (tp );
197+ #endif
183198}
184199
185200/* ------------------------------------------------------------------------- */
@@ -1589,8 +1604,10 @@ static PyGetSetDef WraptObjectProxy_getset[] = {
15891604};
15901605
15911606static struct PyMemberDef WraptObjectProxy_Type_members [] = {
1607+ #ifdef WRAPT_HEAPTYPE_SUPPORT_OFFSET
15921608 {"__weaklistoffset__" , T_PYSSIZET , offsetof(WraptObjectProxyObject , weakreflist ), READONLY },
15931609 {"__dictoffset__" , T_PYSSIZET , offsetof(WraptObjectProxyObject , dict ), READONLY },
1610+ #endif
15941611 {NULL },
15951612};
15961613
@@ -1697,6 +1714,7 @@ static PyType_Spec WraptCallableObjectProxy_Type_spec = {
16971714 "CallableObjectProxy" ,
16981715 sizeof (WraptObjectProxyObject ),
16991716 0 ,
1717+ /* Only define HAVE_GC if the object defines custom traverse and clear */
17001718 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
17011719 WraptCallableObjectProxy_Type_slots
17021720};
@@ -2778,6 +2796,11 @@ init_type(PyObject *module, PyObject **newtype, PyType_Spec *spec,
27782796 return -1 ;
27792797 }
27802798 assert (((PyTypeObject * )* newtype )-> tp_traverse != NULL );
2799+ #ifndef WRAPT_HEAPTYPE_SUPPORT_OFFSET
2800+ /* hack for Python <= 3.8 */
2801+ ((PyTypeObject * )* newtype )-> tp_weaklistoffset = offsetof(WraptObjectProxyObject , weakreflist );
2802+ ((PyTypeObject * )* newtype )-> tp_dictoffset = offsetof(WraptObjectProxyObject , dict );
2803+ #endif
27812804 }
27822805
27832806 if (PyModule_AddObject (module , attrname , * newtype ) < 0 ) {
0 commit comments