@@ -81,12 +81,17 @@ class ffi_type(ctypes.Structure):
8181
8282# The GETFUNC and SETFUNC typedefs from "Modules/_ctypes/ctypes.h".
8383GETFUNC = ctypes .PYFUNCTYPE (ctypes .py_object , ctypes .c_void_p , ctypes .c_ssize_t )
84- # The return type of SETFUNC is declared here as a c_void_p instead of py_object to work
85- # around a ctypes bug (https://github.com/python/cpython/issues/81061). See the comment
86- # in make_callback_returnable's setfunc for details.
87- SETFUNC = ctypes .PYFUNCTYPE (
88- ctypes .c_void_p , ctypes .c_void_p , ctypes .py_object , ctypes .c_ssize_t
89- )
84+ if sys .version_info < (3 , 10 ):
85+ # The return type of SETFUNC is declared here as a c_void_p instead of py_object to work
86+ # around a ctypes bug (https://github.com/python/cpython/issues/81061). See the comment
87+ # in make_callback_returnable's setfunc for details. This bug was fixed in 3.10.
88+ SETFUNC = ctypes .PYFUNCTYPE (
89+ ctypes .c_void_p , ctypes .c_void_p , ctypes .py_object , ctypes .c_ssize_t
90+ )
91+ else :
92+ SETFUNC = ctypes .PYFUNCTYPE (
93+ ctypes .py_object , ctypes .c_void_p , ctypes .py_object , ctypes .c_ssize_t
94+ )
9095
9196
9297if sys .version_info < (3 , 13 ):
@@ -287,20 +292,22 @@ def setfunc(ptr, value, size):
287292 )
288293
289294 ctypes .memmove (ptr , ctypes .addressof (value ), actual_size )
290- # Because of a ctypes bug (https://github.com/python/cpython/issues/81061),
291- # returning None from a callback with restype py_object causes a reference
292- # counting error that can crash Python. To work around this bug, the restype of
293- # SETFUNC is declared as c_void_p instead. This way ctypes performs no automatic
294- # reference counting for the returned object, which avoids the bug. However,
295- # this way we have to manually convert the Python object to a pointer and adjust
296- # its reference count.
297- none_ptr = ctypes .cast (id (None ), ctypes .POINTER (PyObject ))
298- # The return value of a SETFUNC is expected to have an extra reference
299- # (which will be owned by the caller of the SETFUNC).
300- ctypes .pythonapi .Py_IncRef (none_ptr )
301- # The returned pointer must be returned as a plain int, not as a c_void_p,
302- # otherwise ctypes won't recognize it and will raise a TypeError.
303- return ctypes .cast (none_ptr , ctypes .c_void_p ).value
295+
296+ if sys .version_info < (3 , 10 ):
297+ # Because of a ctypes bug (https://github.com/python/cpython/issues/81061),
298+ # returning None from a callback with restype py_object causes a reference
299+ # counting error that can crash Python. To work around this bug, the restype of
300+ # SETFUNC is declared as c_void_p instead. This way ctypes performs no automatic
301+ # reference counting for the returned object, which avoids the bug. However,
302+ # this way we have to manually convert the Python object to a pointer and adjust
303+ # its reference count. This bug was fixed in 3.10.
304+ none_ptr = ctypes .cast (id (None ), ctypes .POINTER (PyObject ))
305+ # The return value of a SETFUNC is expected to have an extra reference
306+ # (which will be owned by the caller of the SETFUNC).
307+ ctypes .pythonapi .Py_IncRef (none_ptr )
308+ # The returned pointer must be returned as a plain int, not as a c_void_p,
309+ # otherwise ctypes won't recognize it and will raise a TypeError.
310+ return ctypes .cast (none_ptr , ctypes .c_void_p ).value
304311
305312 # Store the getfunc and setfunc as attributes on the ctype, so they don't
306313 # get garbage-collected.
0 commit comments