проблема с типами Python в разных ОС




c python-3.x (2)

В 99% случаев причиной являются несоответствия между типами аргументов (и / или возвращаемых) ( stackoverflow.com/questions/52268294/… : один такой пример).

Всегда иметь [Python 3.Docs]: ctypes - библиотека внешних функций для Python, открытая при работе с ctypes .

Я нашел [GitHub]: erikssm / futronics-fingerprint reader - (мастер) futronics-fingerprint-reader / ftrScanAPI.h (я не знаю, насколько он отличается от того, что у вас есть в данный момент, но вещи, которые вы опубликовали, похоже, совпадают ), и я сделал некоторые изменения в вашем коде:

  • Определите argtypes и restype для функций
  • Определите отсутствующие типы (только для ясности)
  • Некоторые другие незначительные изменения (переименовывает)
  • Еще одна вещь, которую я заметил в приведенном выше файле, это макрос #pragma pack(push, 1) (см. [MS.Docs]: pack для более подробной информации). Для этой структуры это не имеет значения (спасибо @AnttiHaapala за подсказку), так как выравнивание членов 3 int ( 4 байта) не изменяется, но для других структур (с «меньшими» типами элементов (например, char , short )) вы Возможно, вы захотите добавить: _pack_ = 1

Ваш модифицированный код (само собой разумеется, я не запускал его, поскольку у меня нет .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...')

Я пытаюсь преобразовать функцию C для Python 3.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...')

определение функции:

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 бит

  • В Windows 10 64 бит
    Я не печатаю "ручка здесь"

    Что я пробовал:
    Согласно некоторым ответам о переполнении стека, это может быть вызвано тем, что я не назначил функции argtypes и restype явно, поэтому я попытался и потерпел неудачу.


  • Вы должны показать свои попытки .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

    Проверьте использование WinDLL против CDLL . Не имеет значения, является ли ваш Python 64-битным, но это имеет значение для 32-битного Python. Используйте CDLL если функции используют соглашение о вызовах C (__cdecl) и WinDLL если функции используют соглашение о вызовах __stdcall. Если заголовочный файл не понятен, по умолчанию обычно используется __cdecl. Изменить: из ссылки API в другом ответе, это __stdcall и следует использовать WinDLL .





    ctypes