为了账号安全,请及时绑定邮箱和手机立即绑定

不同操作系统上的python ctypes问题

不同操作系统上的python ctypes问题

C
缥缈止盈 2020-02-03 12:38:55
我正在尝试将C函数转换为python 3.6使用。代码如下:lib = ctypes.WinDLL('ftrScanAPI.dll') # provided by fingerprint scannerclass FTRSCAN_IMAGE_SIZE(ctypes.Structure):    _fields_ = [    ("nWidth", ctypes.c_int),    ("nHeight", ctypes.c_int),    ("nImageSize", ctypes.c_int)]print('Open device and get device handle...')hDevice = lib.ftrScanOpenDevice()print('handle is', hDevice)print('Get image size...')Image_size = FTRSCAN_IMAGE_SIZE(0, 0, 0)if lib.ftrScanGetImageSize(hDevice, ctypes.byref(Image_size)):    print('Get image size succeed...')    print('  W', Image_size.nWidth)    print('  H', Image_size.nHeight)    print('  Size', Image_size.nImageSize)else:    print('Get image size failed...')函数定义:typedef struct FTR_PACKED __FTRSCAN_IMAGE_SIZE {    int nWidth;    int nHeight;    int nImageSize;} FTRSCAN_IMAGE_SIZE, *PFTRSCAN_IMAGE_SIZE;FTRHANDLE ftrScanOpenDevice();  # typedef void *  FTRHANDLE;BOOL ftrScanGetImageSize(FTRHANDLE ftrHandle,     PFTR_SCAN_IMAGE_SIZE pImageSize);但是具有相同代码的不同操作系统似乎具有不同的结果:在Windows 7 64位上输出1在Windows 10 64位上,我不打印“句柄在这里” 输出2我已尝试的操作:根据有关堆栈溢出的一些答案,这可能是由于未明确分配函数argtypes和restype引起的,所以我尝试并失败了。
查看完整描述

3 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

您应该显示.argtypes和.restype尝试,但是尝试一下:


from ctypes import wintypes as w


class FTRSCAN_IMAGE_SIZE(ctypes.Structure):

    _fields_ = [('nWidth', ctypes.c_int),

                ('nHeight', ctypes.c_int),

                ('nImageSize', ctypes.c_int)]


FTRHANDLE = ctypes.c_void_p


lib = ctypes.WinDLL('ftrScanAPI.dll')

lib.ftrScanOpenDevice.argtypes = None

lib.ftrScanOpenDevice.restype = FTRHANDLE

lib.ftrScanGetImageSize.argtypes = FTRHANDLE,ctypes.POINTER(FTRSCAN_IMAGE_SIZE)

lib.ftrScanGetImageSize.restype = w.BOOL

检查WinDLLvs. 的使用CDLL。您的Python是否为64位并不重要,但在32位Python上却有所不同。使用CDLL如果函数使用C调用约定(__cdecl)和WinDLL若函数使用__stdcall调用约定。如果头文件不清楚,则默认通常为__cdecl。 编辑:从API链接中的另一个答案,它是__stdcall并且WinDLL应该使用。


查看完整回答
反对 回复 2020-02-03
?
繁花如伊

TA贡献2012条经验 获得超12个赞

问题似乎只是设备句柄是一个64位实体(类型定义的指向void的指针)。它可以在Windows 7中正常工作只是偶然,因为句柄的高33位正确为零。


ctypes中所有函数的返回类型默认为32位int。现在,在Windows 10中,似乎已设置了第32位(符号位),当将handle-coerced-to-int推入64位堆栈进行函数调用时,这会导致符号扩展。结果地址的所有高位都设置为(0xFFFFFFFFA ...),它指向内核空间而不是用户空间。


因此,也许您可以使用


lib.ftrScanOpenDevice.restype = c_void_p

这并不是说您不应该为所有函数定义参数和返回类型,而应该-否则,它们将仅遵循C语言的默认参数提升规则,然后工作……或者完全无法工作,具体取决于函数原型本身是否与默认参数提升兼容。例如,如果不定义原型就不能正确调用任何接受floats作为参数的函数。


查看完整回答
反对 回复 2020-02-03
  • 3 回答
  • 0 关注
  • 554 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信