Domanda

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)
È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top