The full class name of this type is ctypes.wintypes.LP_c_long, when I programming a script using win32 API, I sometimes get a HWND object of this type. But the HWND also could be returned as int type.

I get two HWND point to the same window but with different type, compare them with == always return False.

I try to print the value of the HWND, but there is no value attribute, it has a contents attribute but will crash the Python interpreter whenever I try to print it.

I can hardly find any useful documentation or code example about it.

Here is the attribute list of the class

 
['__bool__',
 '__class__',
 '__ctypes_from_outparam__',
 '__delattr__',
 '__delitem__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__setitem__',
 '__setstate__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_b_base_',
 '_b_needsfree_',
 '_objects',
 '_type_',
 'contents']
 

The LP_c_long is a pointer type, like long * p in C, The right way to access the value of this type is treat it like an one element array

 
    LPCLONG = POINTER(c_int)
    aa = LPCLONG(c_int(100))
    print(aa.contents)    
    print(aa[0])    
 

Output

 
c_long(100)
100
 

But the HWND type in Win32 is a handle, not a pointer, the original type in Win32 SDK is void *, I don't know why I get the HWND with LP_c_long type. If you treat a HWND value as a memory address and access it, and the handle value is an illegal address, it will trigger a memory violation exception, that's why print hwnd[0], or hwnd.contents will crash the Python interpreter.

Its certainly a wrong type. What we need is treat it as a DWORD, int, or long or anything else but not a pointer type which represent memory address.

What I need is to cast the pointer type to long or int. Most Win32 APIs in Python will return HWND as int, and I found only the HWND passed by EnumWindowsProc callback function has this type. Here is how I register the callback function

 
EnumWindows(EnumWindowsProc(foreach_window), 0)
 

After carefully reading the documentation at https://docs.python.org/2/library/ctypes.html. I finally figure out the problem, I defined the wrong type with WINFUNCTYPE, the second parameter of the callback function is HWND, it should be c_int, not a pointer

 
# wrong type definition
EnumWindowsProc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int))
 
BOOL CALLBACK EnumWindowsProc(
  HWND hwnd, 
  LPARAM lParam 
);
 
# right type definition
EnumWindowsProc = WINFUNCTYPE(c_bool, c_int, POINTER(c_int))
 
 

Its a hidden bug, when calling Win32 API, there would be no problem because of the implicit type conversion of C language , but Python has no such kind of conversion, actually we don't specify the type of the function parameter in Python, it accept anything passed to it, in this case we accept a handle value but interpreted as pointer, reading the content is the same as read the memory address represented by the HWND value.