使用ctypes获取返回参数的正确方法

2024-09-28 21:01:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我熟悉python,但不熟悉ctypes。在

我一直在玩这个特殊的函数(VCS GetErrorInfo),但无法让它工作。我的问题是访问返回参数。我在Windows 64位上工作,但在Linux下也尝试过。完整的文档和本例中的windows库可以找到here。在

我想调用的函数是这样的。在

BOOL VCS_GetErrorInfo(DWORD ErrorCodeValue, char *pErrorInfo, WORD MaxStrSize)
  • 参数
    • ErrorCodeValue,DWORD,收到的错误代码
    • MaxStrSize,字,错误字符串的最大长度
  • 返回参数
    • pErrorInfo,char*,错误字符串
    • 返回值:BOOL,如果找到错误信息,则返回非零;否则返回0

在pErrorInfo中,我期望“没有通信错误”。在

我的代码(已编辑)。。。在

^{pr2}$

输出

1
c_char_p('')

仍然没有输出。在

错误文档

0x0000 0000, No Communication Error
0x0503 0000, Toggle Error
0x0504 0000, SDO Time Out
...

如果我用另一个错误代码来尝试。在

result = lib.VCS_GetErrorInfo(wintypes.DWORD(0x05030000), ctypes.byref(pErrorInfo), wintypes.WORD(10))
print result
0
c_char_p('')

我可以把ErrorCodeValue传错吗。在

我也尝试过使用Ubuntu的方法:

import ctypes

ctypes.cdll.LoadLibrary("/path/to/libftd2xx.so")
lib = ctypes.cdll.LoadLibrary("/path/to/libEposCmd.so.5.0.0.3")

def VCS_GetErrorInfo(ErrorCodeValue, MaxStrSize):
    lib.VCS_GetErrorInfo.restype = ctypes.c_bool
    error_buf_size = ctypes.create_string_buffer(MaxStrSize)
    pErrorInfo = ctypes.c_char_p(ctypes.addressof(error_buf_size))
    result = lib.VCS_GetErrorInfo(ctypes.c_uint32(ErrorCodeValue), ctypes.byref(pErrorInfo), ctypes.c_uint16(MaxStrSize))
    if not result:
        raise RuntimeError('get error info failed = {}'.format(pErrorInfo.value))
    return pErrorInfo.value

结果看起来很奇怪。在

print repr(VCS_GetErrorInfo(0, 10))
'\x05'
print repr(VCS_GetErrorInfo(0, 20))
'0\xe7$\xd7j\x7f'
print repr(VCS_GetErrorInfo(0x05040000, 20))
RuntimeError: get error info failed =
print repr(VCS_GetErrorInfo(0x05040000, 30))
Segmentation fault (core dumped)

Tags: 参数lib错误errorresultvcsctypesprint
2条回答

DLL使用__cdecl调用约定而不是__stdcall,因此请使用CDLL而不是{}:

>>> from ctypes import *
>>> lib=CDLL('EposCmd64')
>>> buf=create_string_buffer(80)
>>> lib.VCS_GetErrorInfo(0x05030000,buf,80)
1
>>> buf.value
b'Toggle Error'

注意,所有额外的对象构造wintypes.DWORD(0x05030000)都是不必要的。ctypes判断出它是整数还是指针,但需要知道结构和浮点值。在这种情况下不需要,但下面是如何显式定义参数和返回值:

^{pr2}$

它还可以防止由于额外的类型检查和参数匹配而错误地调用函数:

>>> lib.VCS_GetErrorInfo(0x05040000,buf)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: this function takes at least 3 arguments (2 given)

0返回空字符串(无错误):

>>> lib.VCS_GetErrorInfo(0,buf,80)
1
>>> buf.value
b''

通常,我使用如下方法创建错误消息缓冲区:

error_buf_size = ctypes.create_string_buffer(10) # creates a buffer
pErrorInfo = ctypes.c_char_p(ctypes.addressof(error_buf_size)) # creates a pErrorInfo from the error buffer

# And when passing in the function make sure to wrap in the ctypes.byref
result = lib.VCS_GetErrorInfo(wintypes.DWORD(0), ctypes.byref(pErrorInfo), wintypes.WORD(10))

# Later to get the value of the error string
if pErrorInfo.value:
    print (pErrorInfo.value)

检查ctypes文档中的byrefaddressof

相关问题 更多 >