Issues with communicating with USB device through Ctypes and precompiled binaries

316 Views Asked by At

I am having issues using ctypes to connect with a gaussmeter (F.W. Bell 5180). The manufacturer provides DLLs for the interface and a header file called FWB5180.h:

FWB5180.h:

    // The following ifdef block is the standard way of creating macros which make exporting
    // from a DLL simpler. All files within this DLL are compiled with the USB5100_EXPORTS
    // symbol defined on the command line. this symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see
    // USB5100_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef USB5100_EXPORTS
    #define USB5100_API __declspec(dllexport)
    #else
    #define USB5100_API __declspec(dllimport)
    #endif
    extern "C" USB5100_API unsigned int openUSB5100(void);
    extern "C" USB5100_API void closeUSB5100(unsigned int fwb5000ID);
    extern "C" USB5100_API int scpiCommand(unsigned int usbID, char* cmd, char* result, int len);

My ctypes Python code is the following, where all I try to do is initialize the device then close it:

import ctypes,time

# open DLL
path = "C:\\Users\\Roger\\fw_bell_magnetic_field_probe\\usb5100-x64\\x64-dist\\usb5100.dll"
fwbell = ctypes.WinDLL(path)

# define open and close functions with argument and return types 
openUSB5100 = fwbell.openUSB5100 
openUSB5100.argtypes = None
openUSB5100.restype = ctypes.c_int

closeUSB5100 = fwbell.closeUSB5100
closeUSB5100.argtypes = [ctypes.c_int]
closeUSB5100.restype = None

# open device
idn = openUSB5100()
print(idn, type(idn))

# close device
time.sleep(0.1)
closeUSB5100(idn)

Expected behavior: it says elsewhere in the documentation that idn is a four bit unsigned integer, so it should return a number like 10203045. So I would expect an idn like that, and no errors while closing the connection.

Actual behavior: In my code, openUSB5100 always returns 0, whether the device is plugged in or not. The print statement always outputs 0 <class 'int'>. Then, the closeUSB5100 function errors out with something like OSError: exception: access violation reading 0x0000000000000028. I have also tried using different types for idn like c_ulong, but that didn't seem to help.

I'm on Windows 10 using python 3.9. Both are 64-bit, as are the DLLs.

I will note that I can use the gaussmeter using their provided dummy programs so its not strictly a connectivity issue. Though, I think they are using a 32-bit application with 32 bit drivers because when I try to use the DLLs that they seem to use, I get the following error: OSError: [WinError 193] %1 is not a valid Win32 application. When I use the DLLs marked as 64 bit I don't get this error.

Any tips or things to try with my code? This is my first foray into ctypes, so I accept there is likely egregious errors.

EDIT: Here is the exact error message that I am getting.

PS C:\Users\Roger\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist> python .\fw_bell_py.py
Traceback (most recent call last):
  File "C:\Users\Roger\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\fw_bell_py.py", line 30, in <module>
    idn = openUSB5100()
OSError: exception: access violation reading 0x00000000B56B1D68

The last value, 0x ... , typically changes a little bit if I run the code more than once.

Additionally, I have discovered that apparently the gauss meter might be really slow at being ready to use after being detected by the PC. So if I wait a long time between plugging in the device (or monitoring with usb.core.list_devices until something shows up) and running this code, the code always errors out on the open command, it doesn't make it to the close command.

1

There are 1 best solutions below

2
On

There were some issues with the code (see the discussion), but the larger problem is that there is some problem with the DLL files themselves.