Всегда ли необходимо увеличивать пересчет Py_True / Py_False? - PullRequest
3 голосов
/ 07 октября 2019

Я новичок в Python C-API и просматриваю некоторый исходный код, чтобы выбрать его части.

Вот минимальная версия функции, которую я нашел в исходном тексте Cпакет, содержащий модули расширения:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

static PyObject *
modulename_myfunc(PyObject *self, PyObject *args) {

    // Call PyArg_ParseTuple, etc ...

    // Dummy values; in the real function they are calculated
    int is_found = 1;
    Py_ssize_t n_bytes_found = 1024;

    PyObject *result;
    result = Py_BuildValue("(Oi)",
                           is_found ? Py_True : Py_False,  // Py_INCREF?
                           n_bytes_found);
    return result;
}

Вносит ли это небольшую утечку памяти из-за невозможности использования Py_INCREF на Py_True или Py_False? C-API документы для логического объекта кажутся довольно явными о том, что всегда нужно увеличивать / уменьшать Py_True и Py_False.

Если нужно ввести Py_INCREF, как это может быть наиболее правильноиспользуется здесь, предполагая, что Py_RETURN_TRUE / Py_RETURN_FALSE на самом деле не применимы, поскольку возвращается кортеж?

1 Ответ

3 голосов
/ 07 октября 2019

Причина, по которой Py_INCREF здесь не используется, заключается в том, что Py_BuildValue, при передаче объекта с "O" будет увеличивать счетчик ссылок для вас:

O (объект) [PyObject *]

Передача объекта Python нетронутым (за исключением его счетчика ссылок, который увеличивается на единицу). Если переданный объект является указателем NULL, предполагается, что это было вызвано тем, что вызов, генерирующий аргумент, обнаружил ошибку и установил исключение. Следовательно, Py_BuildValue () вернет NULL, но не вызовет исключение. Если исключение еще не возникло, устанавливается SystemError.

Подобное использование вы увидите здесь, например, в самом CPython .

...