Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python ctypes issue on different OSes

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
    output1

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

    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.

  • like image 737
    newman Avatar asked Jan 01 '23 15:01

    newman


    1 Answers

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

    #!/usr/bin/env python
    
    import ctypes as ct
    from ctypes import wintypes as wt
    
    
    # ...
    
    
    class FTRSCAN_IMAGE_SIZE(ct.Structure):
        # _pack_ = 1
        _fields_ = (
            ("nWidth", ct.c_int),
            ("nHeight", ct.c_int),
            ("nImageSize", ct.c_int),
        )
    
    PFTRSCAN_IMAGE_SIZE = ct.POINTER(FTRSCAN_IMAGE_SIZE)
    FTRHANDLE = ct.c_void_p
    
    lib = ct.WinDLL("ftrScanAPI.dll")  # provided by fingerprint scanner
    
    ftrScanOpenDevice = lib.ftrScanOpenDevice
    ftrScanOpenDevice.argtypes = ()
    ftrScanOpenDevice.restype = FTRHANDLE
    
    ftrScanGetImageSize = lib.ftrScanGetImageSize
    ftrScanGetImageSize.argtypes = (FTRHANDLE, PFTRSCAN_IMAGE_SIZE)
    ftrScanGetImageSize.restype = wt.BOOL
    
    print("Open device and get device handle...")
    h_device = ftrScanOpenDevice()
    print("Handle is", h_device)
    print("Get image size...")
    image_size = FTRSCAN_IMAGE_SIZE(0, 0, 0)
    
    if ftrScanGetImageSize(h_device, ct.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...")
    
    like image 160
    CristiFati Avatar answered Jan 12 '23 08:01

    CristiFati