views:

655

answers:

4

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?

A: 

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

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
Ned Batchelder
+6  A: 

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.

S.Lott
A: 

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.

Henrik Gustafsson