given the following code:
import ctypes
ip="192.168.1.1"
thisdll = ctypes.cdll['aDLL']
thisdll.functionThatExpectsAnIP(ip)
how can I correctly pack this for a DLL that expects it as a c_ulong datatype?
I've tried using:
ip_netFrmt = socket.inet_aton(ip)
ip_netFrmt_c = ctypes.c_ulong(ip_netFrmt)
however, the c_ulong()
method returns an error because it needs an integer.
is there a way to use struct.pack
to accomplish this?
The inet_aton returns a string of bytes. This used to be the lingua franca for C-language interfaces.
Here's how to unpack those bytes into a more useful value.
>>> import socket
>>> packed_n= socket.inet_aton("128.0.0.1")
>>> import struct
>>> struct.unpack( "!L", packed_n )
(2147483649L,)
>>> hex(_[0])
'0x80000001L'
This unpacked value can be used with ctypes. The hex thing is just to show you that the unpacked value looks a lot like an IP address.
First a disclaimer: This is just an educated guess.
an ip-address is traditionally represented as four bytes - i.e. xxx.xxx.xxx.xxx, but is really a unsigned long. So you should convert the representation 192.168.1.1 to an unsiged int. you could convert it like this.
ip="192.168.1.1"
ip_long = reduce(lambda x,y:x*256+int(y), ip.split('.'), 0)
There's probably a better way, but this works:
>>> ip = "192.168.1.1"
>>> struct.unpack('>I', struct.pack('BBBB', *map(int, ip.split('.'))))[0]
3232235777L
For a more thorough way of handling IPs (v6, CIDR-style stuff etc) check out how it's done in py-radix, esp. prefix_pton.