Python Forum

Full Version: ctypes and custom data type (structures, pointer to structures)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi everyone,
Recently I've tried to understand how to use ctypes in Python3 (3.8) by loading shared library (.dll, Microsoft Windows OS) from ftdi and referring to this documentation and a header file that came with drivers.
I've successively loaded the library and was able to import functions to test. But I did not completely understood how to use ctypes to define custom data type (e.g.: structures) and then how to pass pointers to this data type to functions.
An example:
Function name: FT_CreateDeviceInfoList
Function signature: FT_STATUS FT_GetDeviceInfoList(FT_DEVICE_LIST_INFO_NODE *pDest,LPDWORD lpdwNumDevs), with:
  • FT_STATUS: an integer;
  • LPDWORD: pointer to 32-bit signed integer;
  • FT_DEVICE_LIST_INFO_NODE: custom data (structure).
FT_DEVICE_LIST_INFO_NODE defined as:
Quote:typedef struct _ft_device_list_info_node {
ULONG Flags;
ULONG Type;
ULONG ID;
DWORD LocId;
char SerialNumber[16];
char Description[64];
FT_HANDLE ftHandle;
} FT_DEVICE_LIST_INFO_NODE;

First I've defined new class as described in ctypes documentation:
Quote:class FT_DEVICE_LIST_INFO_NODE(Structure):
_fields_ = [("Flags", c_ulong), ("Type", c_ulong), ("ID", c_ulong), ("LocId", c_long), ("SerialNumber", c_byte * 16), ("Description", c_byte * 64), ("ftHandle", c_void_p)]

Then I specified the required arguments for the function (I skip the step where I import function from the library and assign it to variable):
Quote:FT_GetDeviceInfoList.argtypes = [POINTER(FT_DEVICE_LIST_INFO_NODE), POINTER(c_long)]

Next step I define an array (list?) of custom objects:
Quote:FT_DEVICE_LIST_INFO_NODE_ARRAY = FT_DEVICE_LIST_INFO_NODE * 10 # array of ten objects as an example. Basically this function emulates malloc and the number of elements is number of USB-FTDI devices detected by the driver
ft_list = FT_DEVICE_LIST_INFO_NODE_ARRAY()

And finally I call the function:
Quote:second_argument = c_long()
test_value = FT_GetDeviceInfoList(POINTER(ft_list), byref(second_argument)) # or FT_GetDeviceInfoList(ft_list, byref(second_argument)), there is no difference?

When I read values from ft_list array structures I get some values but because I do not understand completely what's happening I can't trust these values.
For example in class definition how I can defined a pointer to a char and at the same time reserve some space. When I replace c_byte * 64, c_char * 64 I'm getting dirrerent results (objects). And how can c_byte * 64 even work, I was thinkig this is an array type.
Basically I'm confused on how to propery use / work with ctypes when you dealing with custom data and parameters (structures, pointer to structures, member of structues being pointers with allocation of some space (as in: char var[100]), function pointers, etc).

Thank you for an answer.