Wie man eine Liste / Array von structs von python zu C übergibt

Ich habe eine C-Funktion, die von C und Python abrufbar sein muss.

Ich habe Schwierigkeiten herauszufinden, wie man eine Python-Liste von c-Typ-Strukturen, von denen jeder mehrere verschachtelte Strukturen enthält, an die c-Funktion übergeben kann.

Eine einzelne dieser Strukturen sieht so aus in Python aus:

class STATION_MM_NODE(ctypes.Structure): _fields_ = [ ("signal", MM_STRUCT), ("noise", MM_STRUCT), ("signalWindowLen", ctypes.c_double), ("metadata", SAC_PZ) ] 

Und so in C:

 typedef struct stationMMnode { struct mantleMagStruct *signal; struct mantleMagStruct *noise; double signalWindowLen; SAC_PZ metadata; } stationMMnode_t; 

Die c-Funktion, die ein Array von stationMMnode-Strukturen aufnimmt, kann als:

 double magnitudeCompute_Mw_Mm_Event(stationMMnode_t **stationMMarray, int numStations); 

Zum Beispiel kann ich es rein aus C wie in:

 int testfunc() { stationMMnode_t *node1 = malloc(sizeof(struct stationMMnode)); node1->signalWindowLen = 500; stationMMnode_t *node2 = malloc(sizeof(struct stationMMnode)); node2->signalWindowLen = 100; struct stationMMnode *nodes[2]; nodes[0] = node1; nodes[1] = node2; magnitudeCompute_Mw_Mm_Event(nodes, 2); // Works! } 

In python kann ich eine Liste von Knoten erstellen, die dem c-Array von structs ähnelt:

 stationMMnodes = [] ... node = get_stationMMnode() # Returns a STATION_MM_NODE node.signal = mm_signal node.noise = mm_noise node.metadata = sacPoleZero stationMMnodes.append(node) ... wrap_lib.magnitudeCompute_Mw_Mm_Event(stationMMnodes, numStations) # Does NOT work 

Wo ich die argtypen definiert habe als:

 wrap_lib.magnitudeCompute_Mw_Mm_Event.argtypes = [ctypes.POINTER(STATION_MM_NODE), ctypes.c_int ] 

Das Modell, das ich oben benutze (das Übergeben eines Ctype-Zeigers auf eine C-Style-Struktur zu ac-Funktion, die einen Zeiger auf struct annimmt) scheint gut zu funktionieren, wenn ich einen Zeiger auf eine einzelne Struktur übergebe, aber für einen Zeiger auf Ein Array von Strukturen, scheint es zu brechen. Darüber hinaus bin ich unsicher, was das Python-Speicher-Layout für eine Liste von Strukturen im Vergleich zu einem Array von Zeigern zu struct (wie die C-Funktion erwartet) ist.

Jede Hilfe wäre sehr dankbar!

Update: Ich fand den folgenden Link sehr hilfreich: python ctypes Array von structs

Ich löste mein Problem durch: 1. Deklarieren einer Reihe von Zeigern zu meinem struct:

 nodeArrayType = ctypes.POINTER(STATION_MM_NODE) * 1024 nodeArray = nodeArrayType() nstn = 0 

2. Schreiben einer C-Funktion, um die Member-Strukturen in eine größere Struktur (= einen Knoten) zu verbinden und einen Zeiger auf diese Struktur zurückzugeben – die in nodeArray [] gespeichert ist.

 nodeArray[nstn] = wrap_libmth.libmth.makeNode(node.signal, node.noise, node.metadata) nstn += 1 

3. Fixieren des Argtyps der C-Funktion, die den Zeiger auf das Struktur-Array empfängt:

 wrap_libmth.libmth.magnitudeCompute_Mw_Mm_Event.argtypes = [ctypes.POINTER(ctypes.POINTER(STATION_MM_NODE)), ctypes.c_int] 

Also … ich habe es funktioniert, aber wie die meisten mit Python, ich fühle mich wie ich den Tiger am Schwanz halte, da ich nicht ganz genau verstehe, warum es funktioniert und was (besser) Alternativen wäre (zB, Der C-Hack makeNode (), um einen Zeiger auf eine STATION_MM_NODE-Struktur zurückzugeben, ist weniger als zufriedenstellend – es wäre besser, diese Struktur vollständig in Python zu generieren).

  • C Zeiger Arithmetik in Python
  • Liste vs. int Zuweisung - "Jede Variable ist ein Zeiger"
  • Python-Variablen sind Zeiger?
  • Boost.Python-Konverter für Zeiger funktioniert nicht
  • Python ist die beste Programmiersprache der Welt.