python ctypes問題在不同的操作系統上




python-3.x windows (2)

你應該顯示你的.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

檢查 WinDLLCDLL 的使用。 如果你的 Python 是64位無關緊要,但它對32位Python有所不同。 如果函數使用C調用約定(__cdecl),則使用 WinDLL 如果函數使用__stdcall調用約定,則使用 WinDLL 。 如果頭文件不清除,則默認值通常為__cdecl。 編輯: 在另一個答案的API鏈接中,應該使用 __stdcallWinDLL

我正在嘗試轉換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引起的,所以我嘗試並失敗了。


  • 問題似乎只是設備句柄是一個64位實體(一個指向void的typedef指針)。 它在你的Windows 7中工作只是一個僥倖,因為句柄的高33位正確為零。

    ctypes中所有函數的返回類型默認為32位 int 。 現在在Windows 10中似乎設置了第32位(符號位),當在64位堆棧上按下handle-coerced-to-int進行函數調用時,會導致符號擴展。 結果地址的所有高位都設置為(0xFFFFFFFFA ...),它指向內核空間而不是用戶空間。

    因此,也許你可以讓你的代碼“正常工作”

    lib.ftrScanOpenDevice.restype = c_void_p

    這並不是說您不應該為 所有 函數定義參數和返回類型 - 您應該,否則它們將只遵循C語言的默認參數提升規則,並且工作......或者完全無法工作,具體取決於關於函數的原型本身是否與默認參數促銷兼容。 例如,如果不定義原型,則無法正確調用任何接受 float s 作為參數的函數。





    ctypes