4

I am toying with ctypes… I have the following C code

Edit: The reason I'm trying to figure this out is to make this blog post more correct

sumrange.c

#include <stdio.h>

long sumrange(long);

long sumrange(long arg)
{
    long i, x;
    x = 0L;

    for (i = 0L; i < arg; i++) {
        x = x + i;
    }
    return x;
}

which I compile using the following command (on OSX)

$ gcc -shared -Wl,-install_name,sumrange.so -o ./sumrange.so -fPIC ./sumrange.c

I've implemented the same function in python:

pysumrange = lambda arg: sum(xrange(arg))

Then I run both at the interactive shell:

>>> import ctypes
>>> sumrange = ctypes.CDLL('./sumrange.so')
>>> pysumrange = lambda arg: sum(xrange(arg))
>>> print sumrange.sumrange(10**8), pysumrange(10**8)
... 887459712 4999999950000000

…and the numbers don't match. Why would this be?

I tried using unsigned long long for all the variables in the C code with no effect (same output).

Jiaaro
  • 74,485
  • 42
  • 169
  • 190

1 Answers1

6

long is a 32-bit type, so the C code simply overflows.

Python doesn’t; pysumrange gives you the correct answer.

ctypes doesn’t know that the function’s return type is unsigned long long unless you tell it. See return types in the Python standard library documentation. It says:

By default functions are assumed to return the C int type. Other return types can be specified by setting the restype attribute of the function object.

So perhaps doing this, just before calling the function, will work for you:

sumrange.sumrange.restype = ctypes.c_ulonglong
Jason Orendorff
  • 42,793
  • 6
  • 62
  • 96
  • 3
    It is good practice to also set the argtypes for a ctypes function. `sumrange.sumrange.argtypes = [ctypes.c_long]` – Brian Larsen Sep 13 '12 at 17:07