简体   繁体   中英

Parsing unsigned ints (uint32_t) in python's C api

If I write a function accepting a single unsigned integer ( 0 - 0xFFFFFFFF ), I can use:

uint32_t myInt;
if(!PyArg_ParseTuple(args, "I", &myInt))
    return NULL;

And then from python, I can pass an int or long .

But what if I get passed a list of integers?

uint32_t* myInts;
PyObject* pyMyInts;
PyArg_ParseTuple(args, "O", &pyMyInts);

if (PyList_Check(intsObj)) {
    size_t n = PyList_Size(v);
    myInts = calloc(n, sizeof(*myInts));

    for(size_t i = 0; i < n; i++) {
        PyObject* item = PyList_GetItem(pyMyInts, i);

        // What function do I want here?
        if(!GetAUInt(item, &myInts[i]))
            return NULL;
    }
}

// cleanup calloc'd array on exit, etc

Specifically, my issue is with dealing with:

  • Lists containing a mixture of int s and long s
  • detecting overflow when assigning to the the uint32

You could create a tuple and use the same method you used for a single argument. On the C side, the tuple objects are not really immutable, so it wouldn't be to much trouble.

Also PyLong_AsUnsignedLong could work for you. It accepts int and long objects and raises an error otherwise. But if sizeof(long) is bigger than 4, you might need to check for an upper-bound overflow yourself.

static int 
GetAUInt(PyObject *pylong, uint32_t *myint) {
    static unsigned long MAX = 0xffffffff;
    unsigned long l = PyLong_AsUnsignedLong(pylong);

    if (l == -1 && PyErr_Occurred() || l > MAX) {
        PyErr_SetString(PyExc_OverflowError, "can't convert to uint32_t");
        return false;
    }

    *myint = (uint32_t) l;
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM