Как сохранить конфликты pynput и ctypes? - PullRequest
0 голосов
/ 06 декабря 2018

Я использую этот гем где-то на этом сайте.

import ctypes
import pynput


SendInput = ctypes.windll.user32.SendInput

W = 0x11
A = 0x1E
S = 0x1F
D = 0x20

# C struct redefinitions 
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
    _fields_ = [("wVk", ctypes.c_ushort),
                ("wScan", ctypes.c_ushort),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", ctypes.c_ulong),
                ("wParamL", ctypes.c_short),
                ("wParamH", ctypes.c_ushort)]

class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", ctypes.c_ulong),
                ("dwFlags", ctypes.c_ulong),
                ("time",ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class Input_I(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", Input_I)]

# Actuals Functions

def PressKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def ReleaseKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


# directx scan codes http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
# ganna need to rework pynput for this to work
import time


def asdf():
    while True:
        PressKey(0x11)
        time.sleep(1)
        ReleaseKey(0x11)
        time.sleep(1)

asdf()

Но просто импортировав pynput, возвращает эту ошибку.

ctypes.ArgumentError: аргумент 2:: ожидаемый экземпляр LP_INPUT вместо LP_Input

Этот небольшой сценарий ctypes работает автономно, но я действительно хочу попытаться включить эту механику в остальную часть моей программы.Я не хочу удалять pynput часть моего кода.Это стало довольно большим.

Есть ли какой-нибудь способ помешать им пытаться работать друг с другом?Потому что я думаю, что это потому, что pynput работает больше как оболочка и как бы увеличивает данные, которые он извлекает.Я не знаю точно, все еще учусь.

Причина, по которой мне нужны ctypes, заключается в том, что это единственное найденное мной решение, которое выводит прямой ввод (работает с играми и любыми другими вещами, использующими DirectX).недостаточно информации или если я разместил это уродливым способом.Готов решить этот вопрос с помощью предложений.

Обновление:

Собираюсь узнать c.

Вот и остальная часть ошибки.

Трассировка (последний вызов был последним): Файл "C: /Users/bbdan/PycharmProjects/Playground/directkeys.py", строка 72, в файле asdf (). Файл "C: /Users/bbdan/PycharmProjects/Playground/directkeys.py"., строка 67, в файле asdf PressKey (0x11), файл «C: /Users/bbdan/PycharmProjects/Playground/directkeys.py», строка 50, в файле PressKey ctypes.windll.user32.SendInput (1, ctypes.pointer (x),ctypes.sizeof (x)) ctypes.ArgumentError: аргумент 2:: ожидаемый экземпляр LP_INPUT вместо LP_Input

1 Ответ

0 голосов
/ 06 декабря 2018

Я pip install input и немного поиграл с этим.Я догадался, что Pynput определяет эти структуры, но с немного другими именами, и устанавливает argtypes restype ) для ctypes.windll.user32.SendInput в своих собственных определениях.
Именно поэтому, когда вы пытаетесь предоставить экземпляры ваших структур, он видит, что жалуется на несоответствие типов.

Существует ряд решений, чтобы это исправить.В любом случае, самым простым было просто заменить ваши структуры (они вам больше не нужны) на Pynput .

Примечание : это просто глупая замена, все может быть организовано намного лучше, и я уверен, что Pynput имеет собственный механизм для достижения этой цели, чтобы избавить пользователя от написания этого кода.

2 модифицированных версии PressKey и ReleaseKey :

def PressKeyPynput(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = pynput._util.win32.INPUT_union()
    ii_.ki = pynput._util.win32.KEYBDINPUT(0, hexKeyCode, 0x0008, 0, ctypes.cast(ctypes.pointer(extra), ctypes.c_void_p))
    x = pynput._util.win32.INPUT(ctypes.c_ulong(1), ii_)
    SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def ReleaseKeyPynput(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = pynput._util.win32.INPUT_union()
    ii_.ki = pynput._util.win32.KEYBDINPUT(0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.cast(ctypes.pointer(extra), ctypes.c_void_p))
    x = pynput._util.win32.INPUT(ctypes.c_ulong(1), ii_)
    SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

Примечание : здесь встречается (более сложный) вариант: [SO]: ctypes.ArgumentError при использовании kivy с pywinauto .

...