I have a Python dictionary with the following entries:
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 as:
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 an array of CA using:
CAarray = CA * 2
Now I want to assign Tmp to CAarray in a loop such 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 have been struggling to get the syntax correct, and have failed so far. Help.
On the side, is there any routine/lib which can handle inter-conversion between Python variables and ctypes variables?
I created a test DLL to verify the structure would pass 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's how 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
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With