I'm trying to imitate the behavior of some parts of a C program in Python. They are both reading a binary file where each record is length->data. The C program will pull the length byte from the file, and regardless of whether it's positive or negative, ntohl() will return the correct length. However, in Python, even though the length record is the same value, when it's negative I'm getting an OverflowError:
length: 419495936
ntohl: 281
length: -2147418112
OverflowError: can't convert negative number to unsigned long
as compared to C:
length: 419495936
ntohl: 281
length: -2147418112
ntohl: 384
What am I doing wrong here? How do I get Python to produce the same results as C?
Edit with code
Here's the C code:
while (fread(&rec_len, sizeof(unsigned int), 1, fp1) != 0) {
printf("length: %d\n", rec_len);
rec_len = ntohl(rec_len);
printf("ntohl: %d\n", rec_len);
And here's Python:
with open(file, "rb") as f:
pSize = struct.unpack('<i', f.read(4))[0]
print "length: " + str(pSize)
packetSize = socket.ntohl(pSize)
print "ntohl: " + str(packetSize)
while packetSize > 0:
packet = f.read(packetSize)
pSize = struct.unpack('<i', f.read(4))[0]
print "length: " + str(pSize)
packetSize = socket.ntohl(pSize)
print "ntohl: " + str(packetSize)
You need to pass a positive number to htonl(). If you can't change how you read the value, you can use the following code:
>>> socket.htonl((-2147418112) & 0xffffffff)
384L
EDIT: having looked at your code, you could change struct.unpack to use '<I'
which gives you an unsigned number, or even to use '>I'
or '!I'
which negates the need for ntohl() afterwards.