2017-11-17 1 views
0

Ich habe eine C-Struktur, die wie folgt aussieht:ctypes: Wie definiere ich ein Array einer Struktur als ein Feld einer anderen Struktur?

typedef struct _DXYZ { 
    DXYZSTATE State[]; 
} DXYZ, *PDXYZ 

im Wesentlichen eine Reihe von DXYZSTATE, von unbekannter Größe.

Wenn ich versuche, diese Struktur in ctypes zu deklarieren, bin ich mir nicht sicher, was zu tun ist.

class DXYZ(Structure): 
    _fields_ = [ 
     ('State', ???) 
    ] 

Was verwende ich, um ein Array unbekannter Größe einer Struktur darzustellen?

Wenn es hilft, ist das Beispiel für seine Verwendung in C die folgenden, malloc'd mit einer an anderer Stelle bereitgestellten Größe.

CurrentState = (PDXYZ) malloc(statesize); 
err = update(CurrentState); 

Der Update-Prozess füllt den zuvor zugewiesenen Speicherplatz mit der Struktur aus.

Antwort

2

Hier ist ein Weg, aber es ist nicht schön. ctypes führt keine Variablenarrays in einer Struktur aus, so dass für den Zugriff auf die variablen Daten ein Casting erforderlich ist.

test.c Implementiert eine Testfunktion, die die Variablenstrukturdaten zurückgibt. In diesem Fall habe ich ein Return-Array der Größe 4 hart-codiert, aber es könnte jede Größe haben.

#include <stdlib.h> 

typedef struct STATE { 
    int a; 
    int b; 
} STATE; 

typedef struct DXYZ { 
    int count; 
    STATE state[]; 
} DXYZ, *PDXYZ; 

__declspec(dllexport) PDXYZ get(void) 
{ 
    PDXYZ pDxyz = malloc(sizeof(DXYZ) + sizeof(STATE) * 4); 
    pDxyz->count = 4; 
    pDxyz->state[0].a = 1; 
    pDxyz->state[0].b = 2; 
    pDxyz->state[1].a = 3; 
    pDxyz->state[1].b = 4; 
    pDxyz->state[2].a = 5; 
    pDxyz->state[2].b = 6; 
    pDxyz->state[3].a = 7; 
    pDxyz->state[3].b = 8; 
    return pDxyz; 
} 

__declspec(dllexport) void myfree(PDXYZ pDxyz) 
{ 
    free(pDxyz); 
} 

test.py

from ctypes import * 
import struct 

class State(Structure): 
    _fields_ = [('a',c_int), 
       ('b',c_int)] 

class DXYZ(Structure): 
    _fields_ = [('count',c_int),  # Number of state objects 
       ('state',State * 0)] # Zero-sized array 

# Set the correct arguments and return type for the DLL functions. 
dll = CDLL('test') 
dll.get.argtypes = None 
dll.get.restype = POINTER(DXYZ) 
dll.myfree.argtypes = POINTER(DXYZ), 
dll.myfree.restype = None 

pd = dll.get() # Get the returned pointer 
d = pd.contents # Dereference it. 

print('count =',d.count) 
# Cast a pointer to the zero-sized array to the correct size and dereference it. 
s = cast(byref(d.state),POINTER(State * d.count)).contents 

for c in s: 
    print(c.a,c.b) 

dll.myfree(pd) 

Ausgang:

count = 4 
1 2 
3 4 
5 6 
7 8 
+0

Ich bin nicht sicher, ob ich völlig verstehen, aber es klingt wie funktioniert dies nur, wenn ich festlegen, wie die Daten geschaffen. In meinem Fall habe ich nicht die Kontrolle über die Daten; Es stammt von einer API eines Drittanbieters. Bedeutet das, dass ich keine Ctypes benutzen kann? – user1219358

+0

@ user1219358 Ich baute den Byte-Puffer, um zu simulieren, was Sie von einer API zurückbekommen würden. Ich werde das Beispiel mit einer tatsächlichen C API aktualisieren, wenn ich eine Chance bekomme. –

+0

@ user1219358 Aktualisiertes Beispiel mit einer Test-DLL. –

Verwandte Themen