2017-02-28 20 views
5

mam pythonowego słownika z następujących pozycji:Konwersja słowniku Pythonowi struktury ctypes

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

że chce przekazać to C-funkcją których funkcja jest określona jako:

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

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

Po stronie Pythona utworzyłem równoważną strukturę ctypes:

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

i utworzyłem tablicę urzędów certyfikacji za pomocą:

CAarray = CA * 2 

Teraz chcę przypisać TMP do CAarray w pętli tak, że

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 zostały stara się uzyskać składnia poprawne, a nie udało do tej pory. Wsparcie.

Po stronie, czy istnieje rutyna/lib, które mogą obsługiwać konwersję pomiędzy zmiennymi Pythona i zmiennymi ctypes?

Odpowiedz

0

Niezupełnie tego pewna, ale wydaje się działać:

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 naklejane do Pythona konwencji nazewnictwa chociaż.

+0

Niestety rolika, to nie działa. Kiedy ca_array zostanie przekazany do funkcji C myfunc (patrz zapytanie), otrzymam wszystkie pomieszane wartości. Zauważ, że pierwszym argumentem myfunc jest tablica struktury CA. – Rak

3

Utworzono testową bibliotekę DLL, aby sprawdzić, czy struktura przebiegnie poprawnie.

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

Oto jak nazwał go:

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

wyjściowa:

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

Świetnie! Dzięki Mark, to działa. Kluczową częścią jest kodowanie ciągu znaków przez "utf8". Mógłbym zmodyfikować rozwiązanie Roliki do punktu, w którym wszystkie wartości zostały poprawnie przechwycone przez funkcję C, z wyjątkiem ciągu, który otrzymał tylko pierwszy znak. Twoje rozwiązanie pomogło rozwiązać ostatni fragment ... – Rak

Powiązane problemy