如何防止 pynput 和 ctypes 发生冲突?
How to keep pynput and ctypes from clashing?
我正在使用此网站某处的 gem。
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,returns 这个错误。
ctypes.ArgumentError: argument 2: : expected
LP_INPUT instance instead of LP_Input
这个小的 ctypes 脚本确实可以独立运行,但我真的想尝试将这些机制合并到我的程序的其余部分中。我不想废弃我代码的 pynput 部分。已经变大了。
有什么方法可以阻止他们尝试相互合作吗?因为我认为这是因为 pynput 的工作方式更像是一个包装器,并且在某种程度上增强了它提取的数据。不是很清楚,还在学习中
我需要 ctypes 的原因是因为它是我发现的唯一输出直接输入的解决方案。(适用于游戏和任何使用 directx 的东西。)
抱歉,如果这还不够信息,或者如果我以丑陋的方式发布了它。我愿意通过建议解决这个问题。
更新:
要去学c.
这是错误的其余部分。
Traceback (most recent call last): File
"C:/Users/bbdan/PycharmProjects/Playground/directkeys.py", line 72, in
asdf() File "C:/Users/bbdan/PycharmProjects/Playground/directkeys.py", line 67, in
asdf
PressKey(0x11) File "C:/Users/bbdan/PycharmProjects/Playground/directkeys.py", line 50, in
PressKey
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) ctypes.ArgumentError: argument 2: : expected LP_INPUT instance instead of LP_Input
我pip install input
,玩了一下。我的猜测是正确的,Pynput 定义了这些结构,但名称略有不同,并设置了 argtypes(和 restype) 对于 ctypes.windll.user32.SendInput
它自己的定义。
这就是为什么当您尝试提供结构的实例时,它会抱怨类型不匹配。
有多种解决方案可以解决此问题。无论如何,最简单的方法就是用 Pynput 替换您的结构(您不再需要它们)。
注意:这只是一个愚蠢的替换,事情可以组织得更好,我相信 Pynput 有一个它自己的机制来实现这一点,以避免用户编写这段代码。
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))
注意:这里遇到了一个(更复杂的)变种:.
这个问题是从 here 链接过来的,让我意识到了这个问题。
对于仍然遇到此问题的任何人,pynput 的 master 分支已更新为不在 argtypes
调用,而是一个通用的 ctypes.c_voidp
,它应该与您传递的任何内容兼容。
我正在使用此网站某处的 gem。
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,returns 这个错误。
ctypes.ArgumentError: argument 2: : expected LP_INPUT instance instead of LP_Input
这个小的 ctypes 脚本确实可以独立运行,但我真的想尝试将这些机制合并到我的程序的其余部分中。我不想废弃我代码的 pynput 部分。已经变大了。
有什么方法可以阻止他们尝试相互合作吗?因为我认为这是因为 pynput 的工作方式更像是一个包装器,并且在某种程度上增强了它提取的数据。不是很清楚,还在学习中
我需要 ctypes 的原因是因为它是我发现的唯一输出直接输入的解决方案。(适用于游戏和任何使用 directx 的东西。) 抱歉,如果这还不够信息,或者如果我以丑陋的方式发布了它。我愿意通过建议解决这个问题。
更新:
要去学c.
这是错误的其余部分。
Traceback (most recent call last): File "C:/Users/bbdan/PycharmProjects/Playground/directkeys.py", line 72, in asdf() File "C:/Users/bbdan/PycharmProjects/Playground/directkeys.py", line 67, in asdf PressKey(0x11) File "C:/Users/bbdan/PycharmProjects/Playground/directkeys.py", line 50, in PressKey ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) ctypes.ArgumentError: argument 2: : expected LP_INPUT instance instead of LP_Input
我pip install input
,玩了一下。我的猜测是正确的,Pynput 定义了这些结构,但名称略有不同,并设置了 argtypes(和 restype) 对于 ctypes.windll.user32.SendInput
它自己的定义。
这就是为什么当您尝试提供结构的实例时,它会抱怨类型不匹配。
有多种解决方案可以解决此问题。无论如何,最简单的方法就是用 Pynput 替换您的结构(您不再需要它们)。
注意:这只是一个愚蠢的替换,事情可以组织得更好,我相信 Pynput 有一个它自己的机制来实现这一点,以避免用户编写这段代码。
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))
注意:这里遇到了一个(更复杂的)变种:
这个问题是从 here 链接过来的,让我意识到了这个问题。
对于仍然遇到此问题的任何人,pynput 的 master 分支已更新为不在 argtypes
调用,而是一个通用的 ctypes.c_voidp
,它应该与您传递的任何内容兼容。