Я создаю некоторый код расширения 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;
}