Search code examples
pythonctypes

expected LP_c_short instance instead of _ctypes.PyCStructType


In a software made by someone else I have this function:

Result = GetStatusDownloadFile(self.server,pState,progress)

which according to the description should returns the status and the current progress of the download of a file but when it is executed it says:

ctypes.ArgumentError: argument 2: TypeError: expected LP_c_short instance instead of _ctypes.PyCStructType

In my understanding the error in in the pState. In a guide I've seen that it is defined as an enum

typedef enum {
Error                = -1,
Inactive                = 0,
Config                = 1,
ListenBootMode        = 2,
ClearPattern                = 3,
SetBank                = 4,
ListenBank                = 5,
EraseFlash                = 6,
ListenErased                = 7,
Load                = 8,
Loading                = 9,
Terminate                = 10,
Successful                = 11,

}

So I thought I should define it into a structure like

class pState(Structure):
_fields_ = [("Error", c_short), ("Inactive", c_short), ("Config", c_short),
            ("ListenBootMode", c_short), ("ClearPattern", c_short),("SetBank", c_short),
            ("ClearPattern", c_short),("ListenBank", c_short),("EraseFlash", c_short),("Load", c_short),
            ("Loading", c_short),("Terminate", c_short),("Successful", c_short)]

But I have no idea on how to "convert" it into an LP_c_short


Solution

  • From the error message, the function is expecting the C-equivalent of short* for the second parameter and appears to be using it as an output parameter. Create a ctypes.c_short instance and pass it by reference to the function, then extract the value returned. It will be an integer matching one of the enumeration values.

    import ctypes as ct
    
    ERROR = -1
    INACTIVE = 0
    CONFIG = 1
    LISTENBOOTMODE = 2
    CLEARPATTERN = 3
    SETBANK = 4
    LISTENBANK = 5
    ERASEFLASH = 6
    LISTENERASED = 7
    LOAD = 8
    LOADING = 9
    TERMINATE = 10
    SUCCESSFUL = 11
    
    state = ct.c_short()
    ... # missing code defining GetStatusDownloadFile, self.server, and progress
    result = GetStatusDownloadFile(self.server, ct.byref(state), progress)
    if state.value == SUCCESSFUL:
        ...