如何使用ctypes模块通过引用EnumChildWindows将Python列表作为参数发送?

问题描述

我有以下使用Python win32gui模块调用EnumChildWindows函数的Python代码

import win32gui

def func(hwnd,param):
  param.append(hwnd)
  return True

def code():
  arr = []
  win32gui.EnumChildWindows(win32gui.GetDesktopWindow(),func,arr)
  print(arr)

code()

win32gui.EnumChildWindows允许通过引用在最后一个参数中传递任何Python对象。

我正在尝试使用模块ctypes执行相同的操作。我得到的最接近的是传递C数组而不是python列表,尽管它不是通过引用传递的,因为当我在函数内部更改变量时,它不会在外部更改其值。

以下代码

from ctypes import byref,POINTER,windll,WINFUNCTYPE
from ctypes.wintypes import BOOL,HWND,LParaM

def func(hwnd,param):
  c_arr = HWND * (len(param) + 1)
  param = c_arr(*param)
  param[len(param) - 1] = hwnd
  print(str(param[len(param) - 1]))
  return True

def code():
  py_arr = []
  c_arr = HWND * len(py_arr)
  arr = c_arr(*py_arr)
  WNDENUMPROC = WINFUNCTYPE(BOOL,HWND * len(py_arr))
  windll.user32.EnumChildWindows.argtypes = [HWND,WNDENUMPROC,POINTER(HWND * len(py_arr))]
  windll.user32.EnumChildWindows.restype = BOOL
  windll.user32.EnumChildWindows(windll.user32.GetDesktopWindow(),WNDENUMPROC(func),byref(arr))
  print(arr)

code()

解决方法

经过一段时间的搜索和尝试不同的事情,我在C语言中找到了win32gui的代码。

它使用PyObject对应于ctypes.py_object

下面的工作代码:

from ctypes import byref,py_object,windll,WINFUNCTYPE
from ctypes.wintypes import BOOL,HWND

def func(hwnd,param):
  param.append(hwnd)
  return True

def code():
  arr = []
  WNDENUMPROC = WINFUNCTYPE(BOOL,HWND,py_object)
  windll.user32.EnumChildWindows.argtypes = [HWND,WNDENUMPROC,py_object]
  windll.user32.EnumChildWindows.restype = BOOL
  windll.user32.EnumChildWindows(windll.user32.GetDesktopWindow(),WNDENUMPROC(func),arr)
  print(arr)

code()