2016-07-24 58 views
1

我正在使用ctypes模塊來調用GetTcpTable2。 我一直在慢慢地將C++中的here示例轉換爲Python;但在實地訪問期間會崩潰。Python在現場訪問ctypes時崩潰

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

它試圖訪問dwLocalAddr分開的table[i]時崩潰。

ptcp_table[0].table[i].dwLocalAddr 

但是,它只是在打印ptcp_table[0].table[i]時不會崩潰。 我試過打印和訪問其他字段;但Python只是崩潰。

這裏是我的結構定義:

定義的 GetTcpTable2
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)) 
    ] 

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

我有一個小的預感,在MIB_TCPTABLE2結構的定義;該文件說tableMIB_TCPROW2大小ANY_SIZE的數組;並進一步檢查是從檢查iphlpapi.h文件中得到的。而且我知道POINTER(MIB_TCPROW2)的尺寸不等於MIB_TCPROW2的尺寸。

+1

'MIB_TCPTABLE2'是一個可變大小的結構; 'dwNumEntries'告訴你'table'數組實際上有多大。你如何將它表示爲Python我不知道。 –

+0

@JonathanPotter謝謝你指出這一點。我已經做了一些更多的搜索,並着眼於爲'MIB_TCPTABLE2'創建一個類工廠方法來生成它的變量加長版本。 – jacob

+0

@ J.J.Hakala必須等2天才能做到這一點。 (從現在起3個小時) – jacob

回答

1

我查看了圍繞結構內變長字段的其他ctypes問題,並提出了一個answer,它建議使用工廠方法來生成類定義。

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

我可以用這個知道sizeGetTcpTable2返回到創建一個新的類型。然後,我所要做的就是將的argtypes更改爲接受void *

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