Возврат объектов в Python из C - PullRequest
8 голосов
/ 30 мая 2011

Я прочитал документацию по Python C-API и даже написал несколько модулей расширения.Тем не менее, я все еще немного не уверен относительно точной семантики, когда дело доходит до возвращения объектов Python из функции C.

Ограниченные примеры в документации Python обычно показывают функцию C, которая возвращает результат Py_BuildValue.Теперь Py_BuildValue возвращает New Reference и передает право собственности на эту ссылку переводчику.Итак, могу ли я экстраполировать из этого, что существует общее правило, что любой объект, возвращаемый в Python, должен быть новой ссылкой , и что возвращение объекта из функции C - это то же самое, что передача права собственности на объект черезпереводчику?

Если да, то как насчет случаев, когда вы возвращаете объект, который уже чем-то принадлежит?Например, предположим, что вы пишете функцию C, которая принимает PyObject*, что является tuple, и вы вызываете PyTuple_GetItem для нее и возвращаете результат.PyTuple_GetItem возвращает заимствованную ссылку - это означает, что элемент все еще "принадлежит" кортежу.Итак, должна ли функция C, которая возвращает результат чего-то вроде PyTuple_GetItem, INCREF результат перед возвратом интерпретатору?

Например:

static PyObject* my_extension_module(PyObject* tup)
{
   PyObject* item = PyTuple_GetItem(tup, 1);
   if (!item) { /* handle error */ }

   return item; // <--- DO WE NEED TO INCREF BEFORE RETURNING HERE?
}

1 Ответ

5 голосов
/ 30 мая 2011

Python ожидает, что любая функция, которую вы ему предоставите, вернет новую ссылку, да. Если у вас есть только заимствованная ссылка, вы должны позвонить Py_INCREF, чтобы дать новую ссылку. Если вы вернете заимствованную ссылку, Python продолжит вызывать Py_DECREF (когда это будет сделано со ссылкой), и в конечном итоге это приведет к освобождению объекта, пока он еще используется.

(Это не редкость, когда это «возможное» освобождение происходит при выходе из интерпретатора, и в этом случае может остаться незамеченным, но возвращать заимствованные ссылки по-прежнему ошибочно.)

...