Nekrataal
Nekrataal

Reputation: 1

Ctypes error: Procedure called with not enough arguments (8 bytes missing) or wrong calling convention

I'm working on a python program that needs to retrieve a video stream from an Imperx card (HD-SDI Express VCE-HDEX03). I load the SDK dlls with ctypes (cdll.LoadLibrary()).

I have a communication problem with a function. According to the doc I should do this if I was coding in C++:

VCESDI_EnumData enumData;
enumData.cbSize = sizeof(VCESDI_EnumData);

VCESDI_ENUM hDevEnum = VCESDI_EnumInit();

while(VCESDI_EnumNext(hDevEnum, &enumData) == VCESDI_Err_Success)
{
    // Do some stuff
}

I get the first argument from the following function in my code:

hDevEnum = wintypes.HANDLE(lib.VCESDI_EnumInit()) # hdevEnum = 0 if no card connected otherwise a random number (always around 8000000)

In the doc, VCESDI_EnumData is declared like that:

struct VCESDI_EnumData
{
    UINT32 cbSize; //Size of structure. Should be initialized to sizeof(VCESDI_EnumData) before passing to VCESDI_EnumNext function
    UINT32 dwSlot; //System defined slot number
    VCESDI_DeviceData; //Pointer to device initialization data
    LPCWSTR pSlotName; //Pointer to system defined slot name
}

And I create the second argument like this:

class VCESDI_EnumData(ct.Structure):
    _fields_ = [("cbSize", ct.c_int),
                ("dwSlot", ct.c_int),
                ("deviceData", ct.c_void_p),
                ("pSlotName", ct.c_void_p)]

And the rest of my code:

enumData = VCESDI_EnumData()
enumData.cbSize = ct.sizeof(VCESDI_EnumData)
hDevEnum = wintypes.HANDLE(lib.VCESDI_EnumInit())
while lib.VCESDI_EnumNext(hDevEnum, ct.byref(enumData)) == 0:
    continue

And finally, when I launch my code I get the following error:

File "HD-SDI_script.py", line 39 in <module>
    while lib.VCESDI_EnumNext(hDevEnum, ct.byref(enumData)) == 0:
ValueError: Procedure called with not enough arguments (8 bytes missing) or wrong calling convention

Any idea where the problem might come from?

Upvotes: 0

Views: 1157

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177471

If 32-bit code, use WinDLL instead of CDLL to load the library. On 64-bit they are the same calling convention and it doesn't matter, but 32-bit they are not.

lib = ctypes.WinDLL('example')  # Uses __stdcall calling convention for functions in example.dll.
lib = ctypes.CDLL('example')    # Uses __cdecl calling convention for functions in example.dll.

Upvotes: 2

Related Questions