在 python 的 C api 中解析无符号整数 (uint32_t)
Parsing unsigned ints (uint32_t) in python's C api
如果我编写一个接受单个无符号整数的函数(0
- 0xFFFFFFFF
),我可以使用:
uint32_t myInt;
if(!PyArg_ParseTuple(args, "I", &myInt))
return NULL;
然后从 python,我可以传递 int
或 long
。
但是如果我得到一个整数列表怎么办?
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
具体来说,我的问题是处理:
- 包含
int
和 long
的混合列表
- 在分配给 uint32 时检测到溢出
您可以创建一个元组并使用与用于单个参数的方法相同的方法。在 C 端,元组对象并不是真正不可变的,所以不会有太大的麻烦。
PyLong_AsUnsignedLong
也可以为您效劳。它接受 int 和 long 对象,否则会引发错误。但是如果 sizeof(long)
大于 4,您可能需要自己检查上限溢出。
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;
}
如果我编写一个接受单个无符号整数的函数(0
- 0xFFFFFFFF
),我可以使用:
uint32_t myInt;
if(!PyArg_ParseTuple(args, "I", &myInt))
return NULL;
然后从 python,我可以传递 int
或 long
。
但是如果我得到一个整数列表怎么办?
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
具体来说,我的问题是处理:
- 包含
int
和long
的混合列表 - 在分配给 uint32 时检测到溢出
您可以创建一个元组并使用与用于单个参数的方法相同的方法。在 C 端,元组对象并不是真正不可变的,所以不会有太大的麻烦。
PyLong_AsUnsignedLong
也可以为您效劳。它接受 int 和 long 对象,否则会引发错误。但是如果 sizeof(long)
大于 4,您可能需要自己检查上限溢出。
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;
}