Python C API检查int64是否未签名
我正在使用Python C API编写一个Python3脚本,其中包含一些计算量很大的C部分。在处理int64时,我不知道如何确保输入数字是无符号int64;也就是说,如果它小于0。正如所建议的,我正在将Python C API检查int64是否未签名,python,c,Python,C,我正在使用Python C API编写一个Python3脚本,其中包含一些计算量很大的C部分。在处理int64时,我不知道如何确保输入数字是无符号int64;也就是说,如果它小于0。正如所建议的,我正在将PyArg\u ParseTuple()。这是我的C代码: static PyObject* from_uint64(PyObject* self, PyObject*){ uint64_t input; PyObject* output; if (!PyArg_Par
PyArg\u ParseTuple()。这是我的C代码:
static PyObject* from_uint64(PyObject* self, PyObject*){
uint64_t input;
PyObject* output;
if (!PyArg_ParseTuple(args, "K", &input)){
return PyErr_Format(PyExc_ValueError, "Wrong input: expected unsigned 64-bit integer.");
}
return NULL;
}
但是,使用负参数调用函数不会引发任何错误,并且输入数字被强制转换为无符号。例如,来自_uint64(-1)
的将导致输入=2^64-2
。正如所料,因为没有溢出检查
在解析输入数字之前,确定输入数字是否为负数的正确方法是什么
unsigned long long input = PyLong_AsUnsignedLongLong(args);
然后,您可以向
if (PyErr_Occurred()) {
// handle out of range here
}
如果该数字不适合无符号long
另请参见@Ctx的答案稍作修改后的内容:
解决方案是首先将输入解析为对象(因此,不是直接从args
),然后检查其类型:
static PyObject* from_uint64(PyObject* self, PyObject* args){
PyObject* output;
PyObject* input_obj;
if (!PyArg_ParseTuple(args, "O", &input_obj)){
return PyErr_Format(PyExc_TypeError, "Wrong input: expected py object.");
}
unsigned long long input = PyLong_AsUnsignedLongLong(input_obj);
if(input == -1 && PyErr_Occurred()) {
PyErr_Clear();
return PyErr_Format(PyExc_TypeError, "Parameter must be an unsigned integer type, but got %s", Py_TYPE
(input_obj)->tp_name);
}
正如预期的那样,此代码适用于[0,2^64-1]中的任何输入,并对边界外的整数以及浮点、字符串等非法类型抛出错误。无符号整数不会溢出。C指定它们遵循模运算。还要注意,K
不解析uint64\u t
,而是解析unsigned long
,因此假设uint64\u t
与unsigned long long相同并不严格正确。@AnttiHaapala感谢您的更正,我将添加正确的类型。谢谢您的回答。我仍然存在的唯一问题是输入号码很小的情况-例如,如果从_uint64(2)
调用,现在会抛出错误。我应该从Python中进行一些类型的转换吗?我要接受[0,2^64-1]范围内的任何数字。@FTeod引发了哪个错误?我看不出输入2
有问题的原因。我得到TypeError:需要一个整数
。代码是上面的三行,在if(PyErr_occurrent()){PyErr_Print();return NULL;}