Reputation: 1246
I am trying to play around with Python and ctypes by experimenting with certain Windows APIs. I have a snippet of code that fails and I am not sure why. I have set all the argtypes and the return types as per the MSDN documentation. The error I am getting is: TypeError: an integer is required (got type LP_c_long)
. You can see all of the error in the output section. The thing is as far as I can tell the argtypes and return types are correct and I am not certain what needs fixing.
from ctypes import *
from ctypes import wintypes as w
user32 = windll.user32
kernel32 = windll.kernel32
HOOKPROC = WINFUNCTYPE(HRESULT, c_int, w.WPARAM, w.LPARAM) # Callback function prototype
user32.SetWindowsHookExW.argtypes = [c_int, HOOKPROC, w.HINSTANCE, w.DWORD]
user32.SetWindowsHookExW.restype = w.HHOOK
kernel32.GetModuleHandleW.argtypes = [w.LPCWSTR]
kernel32.GetModuleHandleW.restype = w.HANDLE
user32.GetMessageW.argtypes = [w.LPMSG, w.HWND, w.UINT, w.UINT]
user32.GetMessageW.restype = w.BOOL
user32.CallNextHookEx.argtypes = [w.HHOOK, c_int, w.WPARAM, w.LPARAM]
user32.CallNextHookEx.restype = w.LPLONG
def hook_procedure(nCode, wParam, lParam):
print("Hello...")
#return user32.CallNextHookEx(hook, nCode, wParam, lParam)
return user32.CallNextHookEx(hook, nCode, wParam, c_lParam)
ptr = HOOKPROC(hook_procedure)
hook = user32.SetWindowsHookExW(
13,
ptr,
kernel32.GetModuleHandleW(None),
0
)
msg = w.MSG() # MSG data structure
user32.GetMessageW(byref(msg), 0, 0, 0) # Wait for messages to be posted
Output:
Hello...
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 262, in 'converting callback result'
TypeError: an integer is required (got type LP_c_long)
Exception ignored in: <function hook_procedure at 0x0000025C469551F0>
Upvotes: 0
Views: 1037
Reputation: 177891
The problem is here:
user32.CallNextHookEx.restype = w.LPLONG
CallnextHookEx
returns an LRESULT
which in C is defined as a LONG_PTR
. That isn't a pointer, but is an integer the size of a pointer (4 bytes on 32-bit systems, 8 bytes on 64-bit systems). wintypes
doesn't have that type, but LPARAM
has the same definition (LONG_PTR), so you can use the following for a definition that will work on 32- and 64-bit Python:
from ctypes import wintypes as w
LRESULT = w.LPARAM
...
user32.CallNextHookEx.restype = LRESULT
Upvotes: 1