Python: embalagem um endereço IP como um ctype.c_ulong () para uso com DLL
-
11-07-2019 - |
Pergunta
dado o seguinte código:
import ctypes
ip="192.168.1.1"
thisdll = ctypes.cdll['aDLL']
thisdll.functionThatExpectsAnIP(ip)
como posso corretamente embalar isso para uma DLL que espera que ele como um c_ulong tipo de dados?
Eu tentei usar:
ip_netFrmt = socket.inet_aton(ip)
ip_netFrmt_c = ctypes.c_ulong(ip_netFrmt)
No entanto, o método c_ulong()
retorna um erro porque ele precisa de um inteiro.
Existe uma maneira de usar struct.pack
para alcançar este objetivo?
Solução
O inet_aton retorna uma seqüência de bytes. Isto costumava ser o língua franca para interfaces de língua C.
Veja como descompactar os bytes em um valor mais ú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 descompactado pode ser usado com ctypes. A coisa hex é apenas para mostrar que o valor descompactado se parece muito com um endereço IP.
Outras dicas
Primeiro um aviso:. Este é apenas um palpite
um ip-address é tradicionalmente representado como quatro bytes - ou seja XXX.XXX.XXX.XXX, mas é realmente um unsigned long. Portanto, você deve converter a representação de 192.168.1.1 para um int unsiged. você pode convertê-lo assim.
ip="192.168.1.1"
ip_long = reduce(lambda x,y:x*256+int(y), ip.split('.'), 0)
Há provavelmente uma maneira melhor, mas isso funciona:
>>> ip = "192.168.1.1"
>>> struct.unpack('>I', struct.pack('BBBB', *map(int, ip.split('.'))))[0]
3232235777L
Para uma maneira mais completa de lidar com IPs (v6, material de estilo CIDR etc) verificar a forma como ele é feito em py-radix , esp. prefix_pton .