@@ -81,12 +81,17 @@ class ffi_type(ctypes.Structure):
81
81
82
82
# The GETFUNC and SETFUNC typedefs from "Modules/_ctypes/ctypes.h".
83
83
GETFUNC = 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
+ )
90
95
91
96
92
97
if sys .version_info < (3 , 13 ):
@@ -287,20 +292,22 @@ def setfunc(ptr, value, size):
287
292
)
288
293
289
294
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
304
311
305
312
# Store the getfunc and setfunc as attributes on the ctype, so they don't
306
313
# get garbage-collected.
0 commit comments