Python: impacchettare un indirizzo IP come ctype.c_ulong () per l'uso con DLL
-
11-07-2019 - |
Domanda
dato il seguente codice:
import ctypes
ip="192.168.1.1"
thisdll = ctypes.cdll['aDLL']
thisdll.functionThatExpectsAnIP(ip)
come posso comprimerlo correttamente per una DLL che lo prevede come un tipo di dati c_ulong?
Ho provato a usare:
ip_netFrmt = socket.inet_aton(ip)
ip_netFrmt_c = ctypes.c_ulong(ip_netFrmt)
tuttavia, il metodo c_ulong ()
restituisce un errore perché necessita di un numero intero.
c'è un modo per usare struct.pack
per raggiungere questo obiettivo?
Soluzione
Inet_aton restituisce una stringa di byte. Questa era la lingua franca per le interfacce in linguaggio C.
Ecco come decomprimere quei byte in un valore più utile.
>>> import socket
>>> packed_n= socket.inet_aton("128.0.0.1")
>>> import struct
>>> struct.unpack( "!L", packed_n )
(2147483649L,)
>>> hex(_[0])
'0x80000001L'
Questo valore decompresso può essere utilizzato con i tipi. La cosa esadecimale è solo per mostrarti che il valore decompresso assomiglia molto a un indirizzo IP.
Altri suggerimenti
Prima un disclaimer: questa è solo un'ipotesi colta.
un indirizzo IP è tradizionalmente rappresentato come quattro byte, ovvero xxx.xxx.xxx.xxx, ma è in realtà un lungo senza segno. Quindi dovresti convertire la rappresentazione 192.168.1.1 in un int non modificato. potresti convertirlo in questo modo.
ip="192.168.1.1"
ip_long = reduce(lambda x,y:x*256+int(y), ip.split('.'), 0)
Probabilmente c'è un modo migliore, ma funziona:
>>> ip = "192.168.1.1"
>>> struct.unpack('>I', struct.pack('BBBB', *map(int, ip.split('.'))))[0]
3232235777L
Per un modo più completo di gestione degli IP (v6, roba in stile CIDR, ecc.) controlla come viene fatto in py-radix , esp. prefix_pton .