如何通过Python3 C API快速检查Python int是否适配C long类型
Python3 C API 检查整数是否适配C long类型的便捷方法
在Python3中,没有像Python2里PyInt_AS_LONG()那样直接的快速转换+检查函数,但有两种高效的方式可以完成检查,避免冗余操作:
1. 使用官方公开API:PyLong_AsLongAndOverflow()(推荐)
这是Python3专门提供的API,用于转换长整数并检测溢出,完全符合官方规范,无需依赖内部实现:
#include <Python.h> static int PyLong_FitsInLong(PyObject *obj) { if (!PyLong_Check(obj)) { return 0; // 输入不是Python长整数类型 } long unused_val; int overflow_flag; PyLong_AsLongAndOverflow(obj, &unused_val, &overflow_flag); return overflow_flag == 0; }
这个函数不会在溢出时抛出异常,仅通过overflow_flag返回0(无溢出,适配C long)或非0(溢出,无法适配),比PyLong_AsLong()或PyObject_RichCompare()更高效直接。
2. 利用PyLongObject内部结构(非公开API,谨慎使用)
如果追求极致性能,可以直接读取Python长整数的内部存储字段,但这种方式依赖Python的版本实现,跨版本可能不兼容:
#include <Python.h> #include <limits.h> static int PyLong_FitsInLong(PyObject *obj) { if (!PyLong_Check(obj)) { return 0; } PyLongObject *long_obj = (PyLongObject *)obj; if (long_obj->ob_size == 0) { return 1; // 0必然适配C long } const int long_bits = sizeof(long) * CHAR_BIT - 1; // C long的有效位数(去掉符号位) const int digit_bits = PYLONG_BITS_IN_DIGIT; // Python内部digit的存储位数 const int digit_count = abs(long_obj->ob_size); // 先判断digit数量是否远超C long的容量 if (digit_count * digit_bits > long_bits + 1) { return 0; } // 若digit数量刚好匹配,检查最高位是否超出范围 if (digit_count * digit_bits == long_bits + 1) { unsigned long max_pos = (unsigned long)LONG_MAX; unsigned long max_neg = (unsigned long)(-LONG_MIN); unsigned long top_digit = long_obj->ob_digit[digit_count - 1]; unsigned long threshold = (long_obj->ob_size > 0) ? max_pos : max_neg; threshold >>= ((digit_count - 1) * digit_bits); return top_digit <= threshold; } return 1; }
注意:该方法仅在你明确目标Python版本的内部实现时使用,Python官方可能在后续版本修改PyLongObject的结构。
内容的提问来源于stack exchange,提问作者Dima Pasechnik
相关产品推荐
相关产品推荐

