ctypes mishandles `void` return type · Issue #91353 · python/cpython
On wasm targets, test_code fails. It's because of a bad function pointer cast. The problematic code is as follows:
import ctypes py = ctypes.pythonapi freefunc = ctypes.CFUNCTYPE(None, ctypes.c_voidp) RequestCodeExtraIndex = py._PyEval_RequestCodeExtraIndex RequestCodeExtraIndex.argtypes = (freefunc,) RequestCodeExtraIndex.restype = ctypes.c_ssize_t SetExtra = py._PyCode_SetExtra SetExtra.argtypes = (ctypes.py_object, ctypes.c_ssize_t, ctypes.c_voidp) SetExtra.restype = ctypes.c_int LAST_FREED = None def myfree(ptr): global LAST_FREED LAST_FREED = ptr FREE_FUNC = freefunc(myfree) FREE_INDEX = RequestCodeExtraIndex(FREE_FUNC) # Verify that the provided free function gets invoked # when the code object is cleaned up. f = eval('lambda:42') SetExtra(f.__code__, FREE_INDEX, ctypes.c_voidp(100)) del f # crashes!!
The problem: freefunc = ctypes.CFUNCTYPE(None, ctypes.c_voidp) declares a function with signature int f(void*). However, the definition of freefunc is void f(void*). These function signatures do not agree, and trying to make the call crashes.
Due to a bug(?) ctypes can produce closures that have void return type but it can't produce simple functions with void return type.
Closures code: checks if restype == Py_None and if so gives the callback a void return type
https://github.com/python/cpython/blob/main/Modules/_ctypes/callbacks.c#L381
Direct call code: calls _ctypes_get_ffi_type which never returns ffi_type_void:
| rtype = _ctypes_get_ffi_type(restype); |