Convert Python dictionary to ctypes structure

I have a Python dictionary with the following data:

Tmp={'Name1': [10.0, 20.0, 'Title1', 1], 'Name2': [5.0, 25.0, 'Title2', 2]} 

I want to pass this to a C function, where the function is defined as:

 struct CA { char *Keys; float *Values; char *Title; int Index; }; void myfunc (struct CA *in, int n); 

On the Python side, I created an equivalent ctypes structure like:

 class CA(ctypes.Structure): _fields_ = [("Keys", ctypes.POINTER(ctypes.c_char_p)), ("Values", ctypes.POINTER(ctypes.c_float)), ("Title", ctypes.POINTER(ctypes.c_char_p)), ("Index", ctypes.c_int)] 

and created a CA array using:

 CAarray = CA * 2 

Now I want to assign Tmp to CAarray in a loop so that

 k = Tmp.keys() for (j, _) in enumerate(k): CAarray[j].Keys = _ CAarray[j].Values = Tmp[_][:2] CAarray[j].Title = Tmp[_][2] CAarray[j].Index = Tmp[_][3] 

I am struggling to get the syntax right and still have failed. Reference.

On the other hand, is there any / lib routine that can handle the mutual conversion between Python variables and ctypes variables?

+6
source share
2 answers

I created a test DLL to verify that the structure passed correctly.

 #include <stdio.h> struct CA { char *Keys; float *Values; char *Title; int Index; }; __declspec(dllexport) void myfunc (struct CA *in, int n) { int i; for(i = 0; i < n; ++i) { printf("%d: Keys = %s\n",i,in[i].Keys); printf("%d: Values = %f %f\n",i,in[i].Values[0],in[i].Values[1]); printf("%d: Title = %s\n",i,in[i].Title); printf("%d: Index = %d\n",i,in[i].Index); } } 

Here is what I called it:

 #!python3 from ctypes import * class CA(Structure): _fields_ = [('Keys',c_char_p), ('Values',POINTER(c_float)), ('Title',c_char_p), ('Index',c_int)] Tmp={'Name1': [10.0, 20.0, 'Title1', 1], 'Name2': [5.0, 25.0, 'Title2', 2]} # repackage Tmp as a list of CA structures ca_list = [] for k,v in Tmp.items(): ca = CA() ca.Keys = k.encode('utf8') # Python 3 strings are Unicode, char* needs a byte string ca.Values = (c_float*2)(v[0],v[1]) # Interface unclear, how would target function know how many floats? ca.Title = v[2].encode('utf8') ca.Index = v[3] ca_list.append(ca) # repackage python list of CAs to ctype array of CAs ca_array = (CA * len(ca_list))(*ca_list) dll = CDLL('test') dll.myfunc.argtypes = POINTER(CA),c_int dll.myfunc.restype = None dll.myfunc(ca_array,len(ca_array)) 

Output:

 0: Keys = Name1 0: Values = 10.000000 20.000000 0: Title = Title1 0: Index = 1 1: Keys = Name2 1: Values = 5.000000 25.000000 1: Title = Title2 1: Index = 2 
+4
source

Not quite sure about this, but it works:

 tmp = {'Name1': [10.0, 20.0, 'Title1', 1], 'Name2': [5.0, 25.0, 'Title2', 2]} class CA(ctypes.Structure): _fields_ = [("key", ctypes.POINTER(ctypes.c_wchar_p)), ("values", ctypes.POINTER(ctypes.c_float)), ("title", ctypes.POINTER(ctypes.c_wchar_p)), ("index", ctypes.c_int)] CAArray = CA * 2 ca_array = CAArray() for ca, key in zip(ca_array, tmp): ca.key = ctypes.pointer(ctypes.c_wchar_p(key)) ca.values = ctypes.pointer(ctypes.c_float(tmp[key][0])) ca.title = ctypes.pointer(ctypes.c_wchar_p(tmp[key][2])) ca.index = tmp[key][3] for ca in ca_array: print(ca.key[0], ca.values[0], ca.values[1], ca.title[0], ca.index) 

I stuck with the Python naming conventions though.

0
source

Source: https://habr.com/ru/post/1015332/


All Articles