Python - ctypes和可变缓冲区

时间:2013-09-19 22:05:12

标签: python arguments ctypes

我正在尝试使用ctypes,我无法调用FormatMessage()来正常工作。

这是我到目前为止的代码;我认为唯一的问题是传递一个可变缓冲区;我从ctypes得到一个关于lpBuffer

的ArgumentError
import ctypes
from ctypes.wintypes import DWORD

def main():
    fm = ctypes.windll.kernel32.FormatMessageA
    fm.argtypes = [DWORD,DWORD,DWORD,DWORD,ctypes.wintypes.LPWSTR(),DWORD]

    dwFlags = DWORD(0x1000) # FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM
    lpSource = DWORD(0)
    dwMessageId = DWORD(0x05)
    dwLanguageId = DWORD(0)
    #buf = ctypes.wintypes.LPWSTR()
    #lpBuffer = ctypes.byref(buf)
    lpBuffer = ctypes.create_string_buffer(512)
    nSize = DWORD(512)

    res = fm(dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize)
    print res

我在lpBuffer参数上遇到一个错误,说它是一个错误的类型,但我已经尝试了尽可能多的传入缓冲区的变体。我尝试过这样做:https://gist.github.com/CBWhiz/6135237并设置FORMAT_MESSAGE_ALLOCATE_BUFFER然后传入LPWSTR()byref,我也尝试将argtype,指针和转换更改为各种LPWSTR(),c_char_p等,但无论我做什么,它都在抱怨。

使函数正确执行的正确语法是什么?我知道ctypes可能很有问题,但我没有在文档中找到任何解决问题的东西(我知道文档使用prototype()但我现在想以这种方式这样做)

谢谢

1 个答案:

答案 0 :(得分:1)

以下是argtypes的{​​{1}}定义(对于Unicode,请注意“W”):

FormatMessageW

如果import ctypes from ctypes import wintypes fm = ctypes.windll.kernel32.FormatMessageW fm.argtypes = [ wintypes.DWORD, # dwFlags wintypes.LPCVOID, # lpSource wintypes.DWORD, # dwMessageId wintypes.DWORD, # dwLanguageId wintypes.LPWSTR, # lpBuffer wintypes.DWORD, # nSize wintypes.LPVOID, # Arguments (va_list *) ] FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100 FORMAT_MESSAGE_FROM_SYSTEM = 0x1000 分配缓冲区,则必须将引用传递给FormatMessage。只需lpBuffer参考即可绕过cast。另外,记得调用TypeError来释放缓冲区:

kernel32.LocalFree