PyList_New выделяет количество элементов больше, чем реально использованное, как инициализировать эти неиспользуемые элементы? - PullRequest
0 голосов
/ 08 января 2019

У меня есть программа на C для использования встроенного Python.

В моем C-коде я использую PyList_New (10) для выделения 10 элементов, и я использую PyList_SetItem () для их инициализации, но на самом деле я, возможно, не буду использовать все из них (например, я использовал 8). Таким образом, факт состоит в том, что 8 элементов списка были инициализированы, а 2 из них нет (в коде C они будут иметь значение NULL). После инициализации я вызвал функцию python с помощью PyObject_Call (). Наконец, моя программа была сломана в скрипте Python, потому что указатель NULL.

Итак, я хочу знать, как инициализировать 2 неиспользуемых элемента (возможно, преобразовать их в None)

PS: я не хочу использовать PyList_Append, потому что я слышал, что это немного неэффективно

Мой код C выглядит так:

PyObject *py_func;

int my_func(PyObject *item_value)
{
    my_list = PyList_New(10);

    for (i = 0; i < 8; i++) {
        PyList_SetItem(my_list, i, item_value);
    }

    /* ... */
    PyObject_Call(py_func, my_list, NULL);

    /* ... */
    return 0;
}

Мой код Python выглядит так:

def my_func(aList):
    for item in aList:
        if item:
            # do something

========================================

Вот битый стек интерпретатора Python:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  listiter_next (it=0x7f354defe5c0) at Objects/listobject.c:2782
2782    Objects/listobject.c: No such file or directory.
[Current thread is 1 (Thread 0x7f3558c2e840 (LWP 607))]
(gdb) bt
#0  listiter_next (it=0x7f354defe5c0) at Objects/listobject.c:2782
#1  0x00007f355840cbaa in _PyEval_EvalFrameDefault (f=<optimized out>, 
    throwflag=<optimized out>) at Python/ceval.c:3071
#2  0x00007f3558407b6e in _PyEval_EvalCodeWithName (_co=0x7f3558aba780, 
    globals=<optimized out>, locals=locals@entry=0x0, 
    args=args@entry=0x7f35501b2fe0, argcount=2, kwnames=kwnames@entry=0x0, 
    kwargs=kwargs@entry=0x8, kwcount=kwcount@entry=0, kwstep=kwstep@entry=2, 
    defs=defs@entry=0x0, defcount=defcount@entry=0, kwdefs=kwdefs@entry=0x0, 
    closure=closure@entry=0x0, name=name@entry=0x0, 
    qualname=qualname@entry=0x0) at Python/ceval.c:4139
#3  0x00007f3558408193 in PyEval_EvalCodeEx (_co=<optimized out>, 
    globals=<optimized out>, locals=locals@entry=0x0, 
    args=args@entry=0x7f35501b2fe0, argcount=<optimized out>, 
    kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0x0, 
    defcount=defcount@entry=0, kwdefs=0x0, closure=0x0) at Python/ceval.c:4160
#4  0x00007f3558349076 in function_call (func=0x7f3550a20268, 
    arg=0x7f35501b2fc8, kw=0x0) at Objects/funcobject.c:604
#5  0x00007f3558316c2a in PyObject_Call (func=0x7f3550a20268, 
    args=<optimized out>, kwargs=<optimized out>) at Objects/abstract.c:2246

1 Ответ

0 голосов
/ 08 января 2019

Я не понимаю, как ваш код Python и C идут вместе с my_func, определенным в обоих, но если ваша проблема действительно связана с неинициализированными значениями в списке, это потому, что вы не инициализировали их чем-то, что является допустимым в Python. Указатель C NULL не является. Py_None есть. Из документов:

Py_None - это имя C для специального объекта Python None. Это настоящий питон объект, а не указатель NULL, что означает «ошибку» в большинстве контекстов, как мы имеем видел.

Так что просто установите остальные элементы вашего списка в Py_None (используя Py_INCREF) и все готово.

for (i = 0; i < 8; i++) {
    PyList_SetItem(my_list, i, item_value);
}
for (; i < PyList_Size(my_list); i++) {
    Py_INCREF(Py_None);
    PyList_SetItem(my_list, i, Py_None);
}
...