2017-02-28 4 views
5

ich ein Python-Wörterbuch mit folgenden Einträgen haben:Konvertieren von Python-Wörterbuch zu ctypes Struktur

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

Ich möchte dies auf eine C-Funktion zu übergeben, wo die Funktion ist wie folgt definiert:

struct CA { 
    char *Keys; 
    float *Values; 
    char *Title; 
    int Index; 
}; 

void myfunc (struct CA *in, int n); 

Auf der Python-Seite habe ich eine äquivalente Ctypes-Struktur wie folgt erstellt:

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)] 

und ein Array von CA erstellt mit:

CAarray = CA * 2 

Jetzt möchte ich Tmp zu CAarray in einer Schleife vergeben, so dass

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] 

Ich habe kämpfen die Syntax korrekt zu bekommen, und sind bisher gescheitert. Hilfe.

Auf der Seite gibt es eine Routine/lib, die Interkonvertierung zwischen Python-Variablen und Ctypes-Variablen umgehen kann?

Antwort

0

nicht ganz sicher darüber, aber es scheint zu funktionieren:

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) 

ich aber zu Python-Namenskonventionen klebte.

+0

Leider rolika, funktioniert es nicht. Wenn ca_array an C-Funktion myfunc übergeben wird (siehe die Abfrage), bekomme ich alle vermasselten Werte. Beachten Sie, dass das erste Argument von myfunc ein Array der Struktur CA ist. – Rak

3

Ich erstellte eine Test-DLL, um zu überprüfen, ob die Struktur korrekt übergeben wurde.

#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); 
    } 
} 

Hier ist, wie ich es genannt:

#!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)) 

Ausgang:

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 
+0

Großartig! Danke Mark, es funktioniert. Der entscheidende Teil ist die Codierung der Zeichenfolge durch 'utf8'. Ich könnte Rolikas Lösung so ändern, dass alle Werte korrekt von der C-Funktion erfasst wurden, mit Ausnahme der Zeichenfolge, die nur das erste Zeichen erhalten hat. Ihre Lösung hat geholfen, das letzte bisschen zu lösen ... – Rak