2016-07-24 15 views
1

Ich verwende das Ctypes-Modul, um GetTcpTable2 aufzurufen. Ich habe langsam das Beispiel here in C++ zu Python konvertiert; aber ich stürze bei einem Feldzugriff ab.Python stürzt bei Feldzugriff Ctypes ab

if __name__ == "__main__": 
    ptcp_table = POINTER(MIB_TCPTABLE2)() 
    ptcp_table = cast(create_string_buffer(sizeof(MIB_TCPTABLE2)), 
         POINTER(MIB_TCPTABLE2)) 
    ip_addr = in_addr() 
    size = c_ulong(sizeof(MIB_TCPTABLE2)) 
    retval = GetTcpTable2(ptcp_table, byref(size), TRUE) 
    if retval == ERROR_INSUFFICIENT_BUFFER: 
     ptcp_table = cast(create_string_buffer(size.value), 
          POINTER(MIB_TCPTABLE2)) 
     if not ptcp_table: 
      #throw error 
      pass 

    retval = GetTcpTable2(ptcp_table, byref(size), TRUE) 
    if retval == NO_ERROR: 
     print("Entries %d" % ptcp_table[0].dwNumEntries) 
     for i in range(0, ptcp_table[0].dwNumEntries): 
      print(ptcp_table[0].table[i]) 
      #ip_addr.S_un.S_addr = ptcp_table[0].table[i].dwLocalAddr 
      #ip_addr_string = inet_nota(ip_addr) 
      #print(ip_addr_string) 
      #print(string_at(ip_addr_string)) 

Es stürzt ab, wenn dwLocalAddr abgesehen von table[i] zuzugreifen versuchen.

ptcp_table[0].table[i].dwLocalAddr 

Es stürzt jedoch nicht ab, wenn nur Drucken ptcp_table[0].table[i]. Ich habe versucht, zu drucken und auf andere Felder zuzugreifen; aber Python stürzt einfach ab.

Hier sind meine struct Definitionen:

class MIB_TCPROW2(Structure): 
    _fields_ = [ 
     ("dwState", c_ulong), 
     ("dwLocalAddr", c_ulong), 
     ("dwLocalPort", c_ulong), 
     ("dwRemoteAddr", c_ulong), 
     ("dwRemotePort", c_ulong), 
     ("dwOwningPid", c_ulong), 
     ("dwOffloadState", c_int) 
    ] 


class MIB_TCPTABLE2(Structure): 
    _fields_ = [ 
     ("dwNumEntries", c_ulong), 
     ("table", POINTER(MIB_TCPROW2)) 
    ] 

Definition von GetTcpTable2:

GetTcpTable2 = windll.iphlpapi.GetTcpTable2 
GetTcpTable2.argtypes = [POINTER(MIB_TCPTABLE2), POINTER(c_ulong), c_char] 
GetTcpTable2.restype = c_ulong 

Ich habe eine kleine Ahnung, dass in der Definition der MIB_TCPTABLE2 Struktur; die Dokumentation besagt, dass table ein Array von MIB_TCPROW2 Größe ANY_SIZE ist; und weitere Überprüfung ist, dass ANY_SIZE 1 von der Überprüfung der iphlpapi.h Datei ist. Und ich weiß, dass die Größe von POINTER(MIB_TCPROW2) nicht gleich der Größe von MIB_TCPROW2 ist.

+1

'MIB_TCPTABLE2' ist eine Struktur variabler Größe; 'dwNumEntries' sagt Ihnen, wie groß das' table' Array tatsächlich ist. Wie du das zu Python repräsentierst, habe ich keine Ahnung. –

+0

@ JonathanPotter Vielen Dank, dass Sie darauf hingewiesen haben. Ich habe ein wenig mehr gesucht und über das Erstellen einer Klassenfactory-Methode für 'MIB_TCPTABLE2' nachgedacht, um daraus variable Laufzeitversionen zu generieren. – jacob

+0

@ J.J.Hakala Muss 2 Tage warten, bevor ich das tun kann. (In 3 Stunden) – jacob

Antwort

1

Ich untersuchte andere Ctypes-Fragen, die sich um Felder variabler Länge innerhalb einer Struktur drehen, und kam zu einem answer, der vorschlug, eine Factory-Methode zu verwenden, um die Klassendefinitionen zu erzeugen.

def MIB_TCPTABLE2_FACTORY(size): 
    class MIB_TCPTABLE2(Structure): 
     _fields_ = [ 
      ("dwNumEntries", c_ulong), 
      ("table", MIB_TCPROW2 * size) 
     ] 
    return MIB_TCPTABLE2 

kann ich dieses Wissen nutzen die size von GetTcpTable2 zurück eine neue Art zu erstellen. Und dann muss ich nur die argtypes von GetTcpTable2 ändern, um eine void * zu akzeptieren.

GetTcpTable2.argtypes = [c_void_p, POINTER(c_ulong), c_char]