Как отправить список Python в качестве аргумента по ссылке на EnumChildWindows с использованием модуля ctypes?

#python #winapi #ctypes #pywin32 #win32gui

#python #по WinAPI #ctypes ( типы ) #pywin32 #win32gui #winapi #ctypes

Вопрос:

У меня есть следующий рабочий код 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()
  

Ответ №1:

После некоторого поиска и пробования разных вещей я нашел код win32gui на C.

Он использует 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()