Python: empaquetar una dirección IP como ctype.c_ulong () para usar con DLL
-
11-07-2019 - |
Pregunta
dado el siguiente código:
import ctypes
ip="192.168.1.1"
thisdll = ctypes.cdll['aDLL']
thisdll.functionThatExpectsAnIP(ip)
¿cómo puedo empaquetar esto correctamente para una DLL que lo espera como un tipo de datos c_ulong?
He intentado usar:
ip_netFrmt = socket.inet_aton(ip)
ip_netFrmt_c = ctypes.c_ulong(ip_netFrmt)
sin embargo, el método c_ulong ()
devuelve un error porque necesita un número entero.
¿hay alguna manera de usar struct.pack
para lograr esto?
Solución
El inet_aton devuelve una cadena de bytes. Solía ??ser la lingua franca para las interfaces de lenguaje C.
Aquí se explica cómo descomprimir esos bytes en un valor más útil.
>>> import socket
>>> packed_n= socket.inet_aton("128.0.0.1")
>>> import struct
>>> struct.unpack( "!L", packed_n )
(2147483649L,)
>>> hex(_[0])
'0x80000001L'
Este valor desempaquetado se puede usar con ctypes. Lo hexadecimal es solo para mostrarle que el valor desempaquetado se parece mucho a una dirección IP.
Otros consejos
Primero un descargo de responsabilidad: esto es solo una suposición educada.
una dirección IP se representa tradicionalmente como cuatro bytes, es decir, xxx.xxx.xxx.xxx, pero en realidad es un largo sin signo. Por lo tanto, debe convertir la representación 192.168.1.1 a un int sin escribir. podrías convertirlo así.
ip="192.168.1.1"
ip_long = reduce(lambda x,y:x*256+int(y), ip.split('.'), 0)
Probablemente haya una mejor manera, pero esto funciona:
>>> ip = "192.168.1.1"
>>> struct.unpack('>I', struct.pack('BBBB', *map(int, ip.split('.'))))[0]
3232235777L
Para obtener una forma más completa de manejar IP (v6, material de estilo CIDR, etc.), consulte cómo se hace en py-radix , esp. prefix_pton .