বিভিন্ন OSes উপর python ctypes সমস্যা




python-3.x windows (3)

সমস্যা কেবল ডিভাইস হ্যান্ডেল একটি 64-বিট সত্তা (অকার্যকর একটি typedef'd পয়েন্টার) বলে মনে হয়। যেটি আপনার উইন্ডোজ 7 এ কাজ করে সেটি হ'ল হ্যান্ডেলের উপরের 33 বিট সঠিকভাবে শূন্য ছিল।

Ctypes সমস্ত ফাংশন ফেরত টাইপ ডিফল্ট 32 বিট int । এখন উইন্ডোজ 10 এ মনে হচ্ছে যে 32 তম বিট (সাইন বিট) সেট করা হয়েছে, এটি ফাংশন কলটির 64-বিট স্ট্যাকে হ্যান্ডেল-কোরেড-টু-ইন্টে push করা হলে কোথাও একটি সাইন এক্সটেনশন তৈরি করে। ফলস্বরূপ অ্যাড্রেসটির উপরের উপরের বিট সেট (0xFFFFFFFFA ...) রয়েছে যা ইউজার স্পেসে কার্নেলের স্থান নির্দেশ করে।

সুতরাং সম্ভবত আপনি শুধু আপনার কোড "কাজ" পেতে পারেন

lib.ftrScanOpenDevice.restype = c_void_p

এটি আপনাকে বলতে হবে না যে আপনি যুক্তি এবং সমস্ত ফাংশনগুলির জন্য ফেরত ধরনগুলি সংজ্ঞায়িত করতে হবে না - আপনাকে অন্যথায় সিটি ভাষার ডিফল্ট আর্গুমেন্ট প্রোমোশন নিয়মগুলি অনুসরণ করতে হবে এবং কাজ করতে হবে ... বা সম্পূর্ণরূপে কাজ করতে ব্যর্থ হবে ফাংশন এর প্রোটোটাইপ নিজেই ডিফল্ট আর্গুমেন্ট প্রচারের সাথে সামঞ্জস্যপূর্ণ কিনা তা। উদাহরণস্বরূপ যে কোনও ফাংশন যা ফ্লোটগুলিকে আর্গুমেন্ট হিসাবে গ্রহণ করে তা প্রোটোটাইপ সংজ্ঞায়িত না করে সঠিকভাবে বলা যায় না।

আমি পাইথন 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);

কিন্তু একই কোড সহ বিভিন্ন OSes ভিন্ন ফলাফল বলে মনে হচ্ছে:

  • উইন্ডোজ 7 64 বিট উপর

  • উইন্ডোজ 10 64 বিট উপর
    আমি মুদ্রণ করি না "হ্যান্ডেল এখানে"

    আমি কি চেষ্টা করেছি:
    স্ট্যাক ওভারফ্লোের কিছু উত্তর অনুসারে, এটি ফাংশন আর্গুমেন্টগুলি বরাদ্দ না করে এবং স্পষ্টভাবে পুনরায় টাইপ করার কারণে হতে পারে, তাই আমি চেষ্টা করে ব্যর্থ হয়েছি।


  • Answer #1

    99% ক্ষেত্রে, আর্গুমেন্টগুলির (এবং / অথবা ফেরত) মধ্যে .com/questions/52268294/… অসঙ্গতি ( .com/questions/52268294/… হল এক যেমন উদাহরণ)।

    সর্বদা আছে [পাইথন 3. ডক্স]: ctypes - ctypes সঙ্গে কাজ করার সময় পাইথন খোলা জন্য একটি বিদেশী ফাংশন লাইব্রেরি

    আমি [GitHub] খুঁজে পেয়েছি : erikssm / futronics- ফিঙ্গারপ্রিন্ট-পাঠক - (মাস্টার) ফিট্রোনিয়ান-ফিঙ্গারপ্রিন্ট-পাঠক / ftrScanAPI.h (আমি জানি না যে এটি বর্তমানে আপনার কাছে কতটা আলাদা, কিন্তু আপনি যা পোস্ট করেছেন তা এখন পর্যন্ত মেলে বলে মনে হচ্ছে ), এবং আমি আপনার কোডে কিছু পরিবর্তন করেছি:

    • Argtypes এবং ফাংশন জন্য পুনরায় টাইপ নির্ধারণ
    • অনুপস্থিত ধরনের সংজ্ঞা (শুধুমাত্র স্বচ্ছতার জন্য)
    • কিছু অন্যান্য উল্লেখযোগ্য পরিবর্তন (renames)
    • উপরের ফাইলটিতে আমি লক্ষ্য করেছি অন্য একটি জিনিস, #pragma pack(push, 1) ম্যাক্রো (চেক করুন [MS.Docs]: আরও বিস্তারিত জানার জন্য প্যাক করুন)। এই কাঠামোর জন্য এটি কোনও পার্থক্য সৃষ্টি করে না (ধন্যবাদ @ এন্টি হ্যাপালা ইঙ্গিতের জন্য), কারণ 3 int ( 4 বাইট) সদস্যের সারিবদ্ধকরণ পরিবর্তন হয় না, তবে অন্যান্য কাঠামোর জন্য ("ছোট" সদস্যের ধরনগুলির সাথে (যেমন গৃহস্থালি , সংক্ষিপ্ত )) যোগ করতে চান: _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...')

    Answer #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

    WinDLL বনাম CDLL ব্যবহার চেক করুন। আপনার পাইথন 64-বিট থাকলে এটি কোন ব্যাপার না, তবে এটি 32-বিট Python তে পার্থক্য করে। CDLL যদি CDLL কলিং কনভেনশন ব্যবহার করে তবে সি সি CDLL ব্যবহার করুন যদি ফাংশন সি কলিং কনভেনশন (__cdecl) এবং WinDLL ব্যবহার করে। হেডার ফাইলটি পরিষ্কার না থাকলে ডিফল্টটি সাধারণত __cdecl হয়। সম্পাদনা: API উত্তর থেকে অন্য উত্তরের মধ্যে, এটি __stdcall এবং WinDLL ব্যবহার করা উচিত।





    ctypes