python - अजगर ctypes विभिन्न ओएस पर जारी करता है




python-3.x windows (2)

मैं अजगर के 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);

लेकिन एक ही कोड वाले अलग OS का अलग परिणाम दिखता है:

  • विंडोज 7 64 बिट पर

  • विंडोज 10 64 बिट पर
    मैं प्रिंट नहीं करता "हैंडल यहाँ है"

    मैंने क्या कोशिश की है:
    स्टैक ओवरफ्लो पर कुछ उत्तरों के अनुसार, यह फ़ंक्शन argtypes को निर्दिष्ट नहीं करने और स्पष्ट रूप से पुनर्स्थापित करने के कारण हो सकता है, इसलिए मैंने कोशिश की और असफल रहा।


  • आपको अपने .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 के उपयोग की जाँच करें। यह मायने नहीं रखेगा कि आपका पायथन 64-बिट है, लेकिन यह 32-बिट पायथन पर फर्क करता है। अगर फ़ंक्शन C __stdcall कॉलिंग कन्वेंशन का उपयोग करते हैं, तो फ़ंक्शन C C कन्वेंशन (__cdecl) और WinDLL उपयोग करते हैं, तो CDLL उपयोग करें। यदि हेडर फ़ाइल स्पष्ट नहीं है, तो डिफ़ॉल्ट आमतौर पर __cdecl है। संपादित करें: दूसरे लिंक में एपीआई लिंक से, यह __stdcall और WinDLL का उपयोग किया जाना चाहिए।


    समस्या केवल यह प्रतीत होती है कि डिवाइस हैंडल 64-बिट इकाई है (टाइप करने के लिए एक टाइप्डिफ़ीड सूचक)। यह आपके विंडोज 7 में काम करता है सिर्फ एक अस्थायी था, क्योंकि हैंडल के ऊपरी 33 बिट्स सही ढंग से शून्य थे।

    Ctypes में सभी फ़ंक्शंस का रिटर्न प्रकार 32-बिट int डिफॉल्ट करता है। अब विंडोज 10 में ऐसा लगता है कि 32 वां बिट (साइन बिट) सेट किया गया था, जो फ़ंक्शन कॉल के लिए 64-बिट स्टैक पर हैंडल-कोर्डेड-टू-इंट को धक्का दिए जाने पर कहीं न कहीं एक साइन एक्सटेंशन का कारण बनता है। परिणामी पते में सभी ऊपरी बिट्स सेट हैं (0xFFFFFFFFA ...) जो कर्नेल स्थान को इंगित करता है और उपयोगकर्ता स्थान में नहीं।

    इस प्रकार शायद आप अपना कोड "काम" बस के साथ प्राप्त कर सकते हैं

    lib.ftrScanOpenDevice.restype = c_void_p

    यह कहने के लिए नहीं है कि आप सभी कार्यों के लिए तर्क और वापसी प्रकारों को परिभाषित नहीं करना चाहिए - आपको करना चाहिए, अन्यथा वे सी भाषा के डिफ़ॉल्ट तर्क पदोन्नति नियमों का पालन करेंगे, और काम करेंगे ... या पूरी तरह से काम करने में विफल रहेंगे, निर्भर करता है क्या फ़ंक्शन का प्रोटोटाइप स्वयं डिफ़ॉल्ट तर्क पदोन्नति के साथ संगत है। उदाहरण के लिए कोई भी फ़ंक्शन जो float s को स्वीकार करता है क्योंकि प्रोटोटाइप को परिभाषित किए बिना तर्क को सही ढंग से नहीं कहा जा सकता है।





    ctypes