Расширение Python C: как DECREF массив C PyArrayObjects - PullRequest
0 голосов
/ 28 декабря 2018

Я создаю некоторый код расширения C для python (пример ниже).Часть функции требует от меня итерации массивов, переданных в качестве аргументов, предварительного вычисления для каждого элемента и возврата массива вычисленных значений.

Я использую NpyIter_MultiNew, поскольку он может выполнять итерацию по нескольким массивам итакже создайте соответствующий массив для вывода.

NpyIter_MultiNew требует массив C PyArrayObject * в качестве ввода (здесь op).op заполняется с выхода PyArray_FROM_OTF.Это новые ссылки, поэтому мне нужно очистить код в конце кода.

Вопрос У меня есть вопрос: для чего мне нужно `DECREF?(т.е. что должно идти в <>)

Вариант 1:

Py_XDECREF(op);

Вариант 2:

Py_XDECREF(op[0]);
Py_XDECREF(op[1]);
Py_XDECREF(op[2]);

Вариант 3:

Py_XDECREF(op[0]);
Py_XDECREF(op[1]);
Py_XDECREF(op[2]);
Py_XDECREF(op);

Я думаю, что Py_XDECREF(op[0]) также может быть ненужным.Я подозреваю, что op[0] остается как NULL и просто используется как флаг для NpyIter_MultiNew, чтобы указать создание нового массива.Новый выходной массив восстанавливается из output = NpyIter_GetOperandArray(iter)[0];

Примечание. Ссылки, используемые в PyObject * args_in[2], заимствованы, поэтому INCREF или DECREF не требуется.

static PyObject *
UseArray(PyObject * args){

    PyObject * args_in[2];

    PyArrayObject * op[3] = {NULL, NULL, NULL};
    npy_uint32 op_flags[3];

    PyArrayObject * output = NULL;

    // python inputs
    if (!PyArg_ParseTuple(args, "OO", &args_in[0], &args_in[1])){
        goto fail;
    }

    // output array
    op[0] = NULL;
    op_flags[0] = NPY_ITER_WRITEONLY | NPY_ITER_ALLOCATE;

    // input array
    op[1] = (PyArrayObject *) PyArray_FROM_OTF(args_in[0], NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
    op_flags[1] = NPY_ITER_READONLY;
    if (op[1] == NULL){
        goto fail;
    }
    op[2] = (PyArrayObject *) PyArray_FROM_OTF(args_in[1], NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
    op_flags[2] = NPY_ITER_READONLY;
    if (op[2] == NULL){
        goto fail;
    }

    // iterate
    iter = NpyIter_MultiNew(3, op, NPY_ITER_EXTERNAL_LOOP, NPY_KEEPORDER, NPY_NO_CASTING, op_flags, NULL);
    <<iterator code>>

    // get output array
    output = NpyIter_GetOperandArray(iter)[0];
    Py_INCREF(output);

    if (NpyIter_Deallocate(iter) != NPY_SUCCEED){
        goto fail;
    }

    <<DECREF op>>

    return PyArray_Return(output);

    fail:
        <<DECREF op>>
        Py_XDECREF(output);
        return NULL;
}
...