Problem on ctypes arguments in a DLL function

eryk sun eryksun at gmail.com
Fri Dec 18 05:24:51 EST 2015


On Fri, Dec 18, 2015 at 2:41 AM,  <jfong at ms4.hinet.net> wrote:
> ValueError: Procedure probably called with too many arguments (4 bytes in excess

The function's calling convention is x86 cdecl (CDLL, caller stack
cleanup), but you're using the x86 stdcall convention (WinDLL, callee
stack cleanup). For a 64-bit process they're actually the same, but
you're using 32-bit Python, so you have to pay attention to the
convention.

> _lib = windll.LoadLibrary("C:\\Windows\\System32\\libusb0.dll")

It should simply be

    _lib = CDLL('libusb0')

windll/WinDLL is the wrong calling convention. Everything else is just
a waste of keystrokes. windll.LoadLibrary is an inferior way to call
WinDLL, since it can't pass constructor arguments such as use_errno or
use_last_error. The System32 directory is on the DLL search path, and
Windows will add the .dll extension for you.

The calling convention is declared in the header file lusb0_usb.h [1].
For example:

    struct usb_bus *usb_get_busses(void);

Notice there's no mention of __stdcall there, so it's using the
default cdecl convention.

> _usb_dev_handle = c_void_p

You'll be better off using

    class _usb_dev_handle(Structure):
        pass

    _usb_dev_handle_p = POINTER(_usb_dev_handle)

This provides stronger type safety. c_void_p is too permissive. It's
easier to debug a ctypes ArgumentError than a memory access violation
or data corruption.

[1]: http://sourceforge.net/p/libusb-win32/code/413/tree/trunk/libusb/src/lusb0_usb.h



More information about the Python-list mailing list