The full class name of this type is ctypes.wintypes.LP_c_long, when you enum windows with windll.user32.EnumWindows and your EnumWindowsProc is defined as WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int)), you get a HWND object of type ctypes.wintypes.LP_c_long. This behavior is as expected, because HWND is indeed defined as a pointer, the type definition is typedef HANDLE HWND; and HANDLE is further defined as typedef PVOID HANDLE;. So HWND is a pointer type, but not the pointer type that point to memory address, that's why sometimes it's called opaque pointer. It's more like an ID that identify a resource. The resource represented by the ID value is used by the OS internally, user code knows nothing underlying details about those resources. For user code, the HWND is nothing more than a DWORD value that can be passed around or printed out. When you print LP_c_long in Python, you get something like <__main__.LP_c_long object at 0x010AC210> which is frustrating because it tells nothing useful information. Under the mantra of "Every thing is an object", Python actually treats it as an instance, the print tells you the type of the instance and the memory address it is stored which works not very well with win32 API. To treat HWND as a pointer type is meaningless in Python code.

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))



But the HWND type in Win32 is a handle, not a real pointer, even it's a real pointer, the memory address can be illegal. If you treat a HWND value as a memory address and access it, and the handle value is an illegal address, it may triggers a memory violation exception, that's why print hwnd[0], or hwnd.contents sometimes crashes the Python interpreter.

What we need is to treat it as a DWORD, int, 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 find 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 I finally figure out the problem, it's the way the WINFUNCTYPE is defined, the second parameter of the callback function is HWND, it can 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))

We are taking the advantage of the type conversion of C language, with this window proc definition, our proc will receive HWND as int.

What if all we get a pointer type and want to see the address itself? It's not obvious for beginners, you can't simply print it as mentioned above, the poor documentation exacerbates the problem. After a lot of internet searches, I find two ways to do this:

cast(hwnd, c_void_p).value 

Sometimes the value of HWND can be an illegal memory address, so the second one is safer.