You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Ctypes: Unclear Error Message for WinFunctionType Mismatch in Windows API Calls #125788
When working with Windows API functions (such as SetWindowsHookExW) using ctypes, providing a HOOKPROC callback function of an incorrect type results in an unclear error message. This can be confusing, especially for beginners or when debugging complex scenarios.
Current error message:
TypeError: expected WinFunctionType instance instead of WinFunctionType
Suggested improved error message:
TypeError: expected WinFunctionType with signature (restype=wintypes.LPARAM, argtypes=[ctypes.c_int32, wintypes.WPARAM, wintypes.LPARAM]) but received WinFunctionType with signature (restype=ctypes.c_int, argtypes=[ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM])
Steps to Reproduce:
Create a Python script with the following content:
importctypesimportctypes.wintypesHOOKPROC=ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
user32=ctypes.windll.user32user32.SetWindowsHookExW.argtypes= [ctypes.c_int, HOOKPROC, ctypes.wintypes.HINSTANCE, ctypes.wintypes.DWORD]
user32.SetWindowsHookExW.restype=ctypes.wintypes.HHOOKdefcallback(nCode, wParam, lParam):
returnuser32.CallNextHookEx(None, nCode, wParam, lParam)
pointer=HOOKPROC(callback)
hook_id=user32.SetWindowsHookExW(13, pointer, None, 0) # 13 corresponds to WH_KEYBOARD_LL# At this point, import pynput, which modifies the SetWindowsHookExW functionfrompynputimportkeyboard, mouse# Attempt to set the hook again, which now fails due to type mismatchhook_id=user32.SetWindowsHookExW(13, pointer, None, 0)
Run the script
Expected Result:
A clear error message indicating the mismatch between the expected and provided WinFunctionType, including details about their signatures.
Actual Result:
An unclear error message: "TypeError: expected WinFunctionType instance instead of WinFunctionType"
Python Version: 3.12.7
Operating System: Windows
Suggested Improvement:
Modify the logic in ctypes that generates these error messages to include more detailed information about the expected and actual WinFunctionType instances, such as their return types and argument types. This would greatly improve the readability and usefulness of the error message, especially for beginners and when debugging complex scenarios.
Additional Notes:
This issue becomes apparent when using libraries like pynput that modify Windows API function signatures. A more descriptive error message would help users identify and resolve such conflicts more easily.
Improving an error message is a feature, not a bug, but there shouldn't be any reason why it can't be done here (it just won't be backported to maintenance releases).
(The bugfix in pynput (or the user's own code) is to use ctypes.WinDLL("user32") rather than ctypes.windll.user32 so that they aren't modifying shared objects. This should already be documented, I'm pretty sure.)
Improving an error message is a feature, not a bug, but there shouldn't be any reason why it can't be done here (it just won't be backported to maintenance releases).
(The bugfix in pynput (or the user's own code) is to use ctypes.WinDLL("user32") rather than ctypes.windll.user32 so that they aren't modifying shared objects. This should already be documented, I'm pretty sure.)
I worked through a local proposal for this. The mismatch is handled by CDataType_from_param_impl() in Modules/_ctypes/_ctypes.c; callback function types currently reach its generic type error, where both types have the same tp_name.
For mismatched ctypes callback types, the proposed special case uses each callback type's StgInfo to show the expected and actual return and argument types, while leaving the existing generic error unchanged for other mismatches:
The resulting message is in the familiar “expected …, got …” form, for example:
expected CFunctionType with signature (restype=<class 'ctypes.c_float'>, argtypes=(<class 'ctypes.c_void_p'>,)), got CFunctionType with signature (restype=<class 'ctypes.c_double'>, argtypes=(<class 'ctypes.c_short'>,))
I added a regression test in Lib/test/test_ctypes/test_parameters.py that passes a callback with a different restype and argtype and checks that both signatures appear in the TypeError. I also added a Misc/NEWS.d/next/Library entry.
On my local Windows Release build, the focused test passed and the complete test_ctypes suite passed (701 tests run, 43 skipped). This proposal is for the in-development branch; I have not tested the reporter's exact pynput scenario.
Activity
zooba commentedon Oct 21, 2024
Improving an error message is a feature, not a bug, but there shouldn't be any reason why it can't be done here (it just won't be backported to maintenance releases).
(The bugfix in
pynput(or the user's own code) is to usectypes.WinDLL("user32")rather thanctypes.windll.user32so that they aren't modifying shared objects. This should already be documented, I'm pretty sure.)songyuc commentedon Oct 29, 2024
Thanks sincerely for your guide!
Replace cdll with CDLL and windll with WinDLL
Replace cdll with CDLL and windll with WinDLL
diegogimenez04 commentedon Jun 9, 2026
Hello everyone. Is this still an issue? If not, I suggest closing it
ZeroIntensity commentedon Oct 20, 2026
Yes, this is still valid. This also isn't specific to Windows; here's a Linux repro:
assilrguez commentedon Oct 23, 2026
I worked through a local proposal for this. The mismatch is handled by
CDataType_from_param_impl()inModules/_ctypes/_ctypes.c; callback function types currently reach its generic type error, where both types have the sametp_name.For mismatched ctypes callback types, the proposed special case uses each callback type's
StgInfoto show the expected and actual return and argument types, while leaving the existing generic error unchanged for other mismatches:The resulting message is in the familiar “expected …, got …” form, for example:
I added a regression test in
Lib/test/test_ctypes/test_parameters.pythat passes a callback with a different restype and argtype and checks that both signatures appear in theTypeError. I also added aMisc/NEWS.d/next/Libraryentry.On my local Windows Release build, the focused test passed and the complete
test_ctypessuite passed (701 tests run, 43 skipped). This proposal is for the in-development branch; I have not tested the reporter's exactpynputscenario.