我正在尝试转换C函数以供Python3.6使用。在
代码如下:
lib = ctypes.WinDLL('ftrScanAPI.dll') # provided by fingerprint scanner
class 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...')
功能定义:
^{pr2}$但是使用相同代码的不同操作系统似乎有不同的结果:
我所做的:
因此,根据某些类型,restype可能不会显式地分配堆栈并导致溢出。在
问题似乎很简单,设备句柄是一个64位实体(指向void的typedef指针)。它能在Windows7中正常工作只是一种侥幸,因为手柄的上33位是正确的零。在
ctypes中所有函数的返回类型默认为32位
int
。现在在Windows10中,似乎设置了第32位(符号位),当强制为int的句柄被推到64位堆栈上进行函数调用时,会在某个地方产生符号扩展。结果地址设置了所有高位(0xFFFFFFFFA…),指向内核空间而不是用户空间。在因此,也许您可以使用
这并不是说您不应该为所有函数定义参数和返回类型-您应该这样做,否则它们将只遵循C语言的默认参数提升规则,并且可以工作。。。或者完全失败,这取决于函数的原型本身是否与默认参数提升兼容。例如,任何接受
float
s作为参数的函数都不能在没有定义原型的情况下正确调用。在{- 为函数定义argtypes和restype
- 定义缺失类型(仅为清晰起见)
- 其他一些不重要的更改(重命名)
- 在上面的文件中,我还注意到了一个
使用ctypes时,始终打开[Python 3.Docs]: ctypes - A foreign function library for Python。在
我找到了[GitHub]: erikssm/futronics-fingerprint-reader - (master) futronics-fingerprint-reader/ftrScanAPI.h(我不知道它与您当前拥有的有多大不同,但是您目前发布的内容似乎匹配),我对您的代码做了一些更改:
#pragma pack(push, 1)
宏(查看[MS.Docs]: pack获取更多详细信息)。对于这个结构,它没有什么区别(感谢@AnttiHaapala的提示),因为3int(4字节)成员对齐方式没有改变,但是对于其他结构(具有“更小”成员类型(例如char,short)您可能需要添加:_pack_ = 1
你修改过的代码(不用说,我没有运行它,因为我没有.dll):
您应该显示.argtypes和.restype尝试,但请尝试一下:
检查}。在
WinDLL
与CDLL
的用法。如果Python的Python是64位的,这并不重要,但是对于32位Python来说,它会有所不同。如果函数使用C调用约定(u cdecl),则使用CDLL
;如果函数使用u stdcall调用约定,则使用WinDLL
。如果头文件不清除,则默认值通常为u cdecl。编辑:在另一个答案的API链接中,应该使用__stdcall
和{相关问题 更多 >
编程相关推荐