我目前正在进入ctypes
模块,并尝试使用^{HWND
句柄调用user32函数^{ctypes.windll.user32.GetWindowText
调用函数。尽管我在将lpString
参数声明为输出参数时遇到问题。在
我的第一次尝试是这样的:
GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",LPCSTR,2),
("nMaxCount",c_int,1)
)
(cfunc
是我找到的一个小包装器here)
一旦调用此原型,就会产生以下异常:
^{pr2}$我认为任何输出变量都必须是POINTER(...)
类型,因此我将定义改为:
GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char),2),
("nMaxCount",c_int,1)
)
但这也产生了一个例外:
chars,name = user32.GetWindowText(handle,255)
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: wrong type
我希望有人知道如何使用ctypes
原型来正确调用GetWindowText
函数。在
编辑:
通过进一步的研究,我至少可以让它发挥作用。我修复的第一个问题是cfunc()
的用法,它有错误的调用说明符。我定义了该函数的精确副本,并将其命名为winfunc()
,并将return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))
替换为return WINFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))
。在
然后我进一步检查了原型。看起来,如果您将("someParameter",POINTER(aType),2)
传递给WINFUNCTYPE
,它将在调用时创建一个aType
对象,并将指向该对象的指针传递给函数。在返回的元组中,您可以访问aType
对象。这带来了另一个问题。cstring是一个字符数组;因此需要告诉ctypes创建一个c_char array
。这意味着:
GetWindowText = winfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char*255),2),
("nMaxCount",c_int,1)
)
很好用。但不幸的是,ctypes现在将传递一个指向cstring的指针,该指针总是255个字符长,忽略了nMaxCount
指定的大小。在
在我看来,我认为没有办法让这个函数与定义为输出参数的动态大小的cstring一起工作。唯一的可能性似乎是不使用输出参数特性,而将LPCSTR
定义为输入参数。然后被调用者需要用ctypes.create_string_buffer()
自己创建一个缓冲区,并将其传递给函数(就像在C中一样)。在
是的。你必须为每个调用创建缓冲区。如果让函数定义来做,那么以后如何访问缓冲区?在
您似乎还必须告诉它期望一个带有}。但不知道为什么会这样。在
POINTER(c_char)
的指针c_char
,而不仅仅是c_char_p
或{无论如何,这应该是有效的:
必须为out参数创建一个字符串缓冲区。可以将函数包装起来,使其稍微透明:
或者在这种情况下,您可以使用pywin32:
^{pr2}$相关问题 更多 >
编程相关推荐