我一直在努力在Cpython C API中拥有一些在序列或可迭代的通用方法。下面的示例代码在编译时没有出错,但在运行以下代码时却失败了。
it ok
Segmentation fault: 11
我猜测是在以下阶段失败了: while ((item = PyIter_Next(it)))
行,但这几乎没有争议,因为等价的python是非常标准的。
x = [1,2,3]
it = iter(x)
for i in it:
print(i)
很明显,我在C语言的等价物上做错了什么。如果有任何帮助或指导,我将不胜感激
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program);
Py_Initialize();
// create list
PyObject *list = PyList_New(2);
PyObject *n1 = PyLong_FromLong(1);
PyObject *n2 = PyLong_FromLong(2);
PyList_Append(list, n1);
PyList_Append(list, n2);
PyObject *it = PyObject_GetIter(list);
PyObject *item;
int i = 0;
if (it) {
printf("it ok\n");
while ((item = PyIter_Next(it))) {
if (PyLong_Check(item)) {
i++;
long long_item = PyLong_AsLong(item);
printf("%d long: %ld", i, long_item);
} else if PyFloat_Check(item) {
i++;
float float_item = PyFloat_AsDouble(item);
printf("%d float: %f", i, float_item);
} else if PyUnicode_Check(item) {
i++;
const char *unicode_item = PyUnicode_AsUTF8(item);
printf("%d unicode: %s", i, unicode_item);
} else continue;
Py_DECREF(item);
Py_DECREF(it);
}
} else {
if (PyErr_Occurred()) {
PyErr_Print();
}
Py_DECREF(n1);
Py_DECREF(n2);
Py_DECREF(list);
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
}
为了回应 @DavidW 对我的错误的有益观察,这里是更正后的代码,也许对其他人来说是个有用的例子。
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program);
Py_Initialize();
// create list
PyObject *list = PyList_New(0); // empty list
PyObject *n1 = PyLong_FromLong(10);
PyObject *n2 = PyLong_FromLong(20);
PyList_Append(list, n1);
PyList_Append(list, n2);
PyObject *iter;
PyObject *item;
int i = 0;
if ((iter = PyObject_GetIter(list)) == NULL) {
return -1;
}
while ((item = PyIter_Next(iter)) != NULL) {
if (PyLong_Check(item)) {
i++;
long long_item = PyLong_AsLong(item);
printf("%d long: %ld\n", i, long_item);
}
if PyFloat_Check(item) {
i++;
float float_item = PyFloat_AsDouble(item);
printf("%d float: %f\n", i, float_item);
}
if PyUnicode_Check(item) {
i++;
const char *unicode_item = PyUnicode_AsUTF8(item);
printf("%d unicode: %s\n", i, unicode_item);
}
Py_DECREF(item);
}
Py_DECREF(iter);
Py_DECREF(n1);
Py_DECREF(n2);
Py_DECREF(list);
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
PyObject *list = PyList_New(2);
这将创建一个长度为2的列表,内容未初始化(可能是 NULL
指针,但我不是100%确定)。)
PyList_Append(list, n1);
PyList_Append(list, n2);
这些附加到列表的末尾(即位置3和4)。
因此你有一个列表 <garbage>, <garbage>, n1, n2
.
你要么更换 PyList_Append
与 PyList_SetItem
或替换 PyList_New(2)
与 PyList_New(0)
.
Py_DECREF(it);
应该在迭代完成后,而不是在循环中完成。