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

How to send a Python list as argument by reference to EnumChildWindows using the ctypes module?

我有以下有效的 Python 代码,它使用模块 win32gui 来调用 EnumChildWindows 函数:

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, 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 which corresponds to 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()