不同操作系统上的python ctypes问题 [英] python ctypes issue on different OSes

查看:104
本文介绍了不同操作系统上的python ctypes问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将C函数转换为python 3.6使用。



代码如下:

  lib = ctypes.WinDLL(' ftrScanAPI.dll')#由指纹扫描仪
类FTRSCAN_IMAGE_SIZE(ctypes.Structure)提供:
_fields_ = [
( nWidth,ctypes.c_int),
( nHeight ,ctypes.c_int),
( nImageSize,ctypes.c_int)
]

print('打开设备并获取设备句柄...')
hDevice = lib.ftrScanOpenDevice()
print('handle is',hDevice)
print('Get image size ...')
Image_size = FTRSCAN_IMAGE_SIZE(0,0,0)
如果lib.ftrScanGetImageSize(hDevice,ctypes.byref(Image_size)):
print('成功获取图像大小...')
print('W',Image_size.nWidth)
print('H',Image_size.nHeight)
print('Size',Image_size.nImageSize)
else:
print('获取图像尺寸失败...')

函数定义:

  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);

但是具有相同代码的不同OS 似乎具有不同的结果:< br>

  • 在Windows 7 64位上



    我做什么已经尝试过:

    根据堆栈溢出的一些答案,这可能是由于未明确分配函数argtypes和restype所致,所以我尝试并失败了。

    解决方案

    99%的情况下,导致参数(和/或返回)类型不一致的原因(请检查 [SO]:通过ctypes从Python调用的C函数返回错误值(@CristiFati的回答)了解更多信息)。


    始终具有 [Python 3.Docs]:ctypes-Python的外部函数库在使用 ctypes


    我发现 [GitHub]:erikssm / futronics-fingerprint-reader-(master)futronics-fingerprint-reader / ftrScanAPI.h (我不知道它与您当前的有什么不同,但到目前为止您发布的内容似乎匹配),并且我对您的代码做了一些更改:



    • 定义 argtypes restype (针对函数)

    • 定义缺失的类型(仅出于清晰目的)

    • 一些其他无关紧要的更改(重命名)

    • 我在上述f中注意到的另一件事ile是 #pragma pack(push,1)宏(请检查 [MS.Docs]:打包以获取更多详细信息)。对于此结构,它没有任何区别(感谢@AnttiHaapala作为提示),因为3个 int 4 字节)成员的对齐方式没有变化,但是对于其他结构(具有较小成员类型(例如 char short )的用户,可能需要添加: _pack_ = 1


    您修改后的代码(不用说,我没有运行它,因为我没有 .dll ) :

     从ctypes导入wintypes 

    #...

    lib = ctypes.WinDLL('ftrScanAPI.dll')#由指纹扫描仪提供
    类FTRSCAN_IMAGE_SIZE(ctypes.Structure):
    #_pack_ = 1
    _fields_ = [[
    ( nWidth,ctypes.c_int),
    ( nHeight,ctypes.c_int),
    ( nImageSize,ctypes.c_int),
    ]

    PFTRSCAN_IMAGE_SIZE = ctypes.POINTER(FTRSCAN_IMAGE_SIZE)
    FTRHANDLE = ctypes.c_void_p

    print('打开设备并获得设备e handle ...')

    lib.ftrScanOpenDevice.argtypes = []
    lib.ftrScanOpenDevice.restype = FTRHANDLE

    h_device = lib.ftrScanOpenDevice()
    print('handle is',h_device)
    print('Get image size ...')
    image_size = FTRSCAN_IMAGE_SIZE(0,0,0)

    lib .ftrScanGetImageSize.argtypes = [FTRHANDLE,PFTRSCAN_IMAGE_SIZE]
    lib.ftrScanGetImageSize.restype = wintypes.BOOL

    如果lib.ftrScanGetImageSize(h_device,ctypes.byref(image_size)):
    print('成功获取图像大小...')
    print('W',image_size.nHeight)
    print('H',image_size.nHeight)
    print('Size', image_size.nImageSize)
    else:
    print('获取图像大小失败...')


    I'm trying to convert C function for python 3.6 use.

    code as below:

    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...')
    

    function definition:

    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);
    

    But different OSes with the same code seems to have different result:

  • On Windows 7 64 bit

  • On Windows 10 64 bit
    I don't print "handle is here"

    What I've tried:
    According to some answers on stack overflow, this may be caused by not assigning function argtypes and restype explicitly, so I tried and failed.

    解决方案

    In 99% of the cases, inconsistencies between arguments (and / or return) type inconsistencies are the cause (check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for more details).

    Always have [Python 3.Docs]: ctypes - A foreign function library for Python open when working with ctypes.

    I found [GitHub]: erikssm/futronics-fingerprint-reader - (master) futronics-fingerprint-reader/ftrScanAPI.h (I don't know how different it's from what you currently have, but things you posted so far seem to match), and I did some changes to your code:

    • Define argtypes and restype for functions
    • Define missing types (for clarity only)
    • Some other insignificant changes (renames)
    • One other thing that I noticed in the above file, is a #pragma pack(push, 1) macro (check [MS.Docs]: pack for more details). For this structure it makes no difference (thanks @AnttiHaapala for the hint), as the 3 int (4 byte) members alignment doesn't change, but for other structures (with "smaller" member types (e.g. char, short)) you might want to add: _pack_ = 1

    Your modified code (needless to say, I didn't run it as I don't have the .dll):

    from ctypes import wintypes
    
    # ...
    
    lib = ctypes.WinDLL('ftrScanAPI.dll') # provided by fingerprint scanner
    class FTRSCAN_IMAGE_SIZE(ctypes.Structure):
        # _pack_ = 1
        _fields_ = [
            ("nWidth", ctypes.c_int),
            ("nHeight", ctypes.c_int),
            ("nImageSize", ctypes.c_int),
        ]
    
    PFTRSCAN_IMAGE_SIZE = ctypes.POINTER(FTRSCAN_IMAGE_SIZE)
    FTRHANDLE = ctypes.c_void_p
    
    print('Open device and get device handle...')
    
    lib.ftrScanOpenDevice.argtypes = []
    lib.ftrScanOpenDevice.restype = FTRHANDLE
    
    h_device = lib.ftrScanOpenDevice()
    print('handle is', h_device)
    print('Get image size...')
    image_size = FTRSCAN_IMAGE_SIZE(0, 0, 0)
    
    lib.ftrScanGetImageSize.argtypes = [FTRHANDLE, PFTRSCAN_IMAGE_SIZE]
    lib.ftrScanGetImageSize.restype = wintypes.BOOL
    
    if lib.ftrScanGetImageSize(h_device, 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...')
    

    这篇关于不同操作系统上的python ctypes问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆