Большая часть этого описана в Подробности подсчета ссылок , а остальное - в документации по конкретным вопросам, которые вы задаете. Но, чтобы получить все это в одном месте:
Py_DECREF(Py_None)
это плохо ... но верно ли это для любой константы?
Более общее правило заключается в том, что вызов Py_DECREF
для всего, на что вы не получили новую / украденную ссылку и не вызывал Py_INCREF
, является плохой вещью. Поскольку вы никогда не вызываете Py_INCREF
для чего-либо доступного в качестве константы, это означает, что вы никогда не вызываете Py_DECREF
для них.
Нужно ли уменьшать refcount для всего, что создано PyWhatever_New()
Да. Все, что возвращает «новую ссылку», должно быть уменьшено. По соглашению все, что заканчивается на _New
, должно возвращать новую ссылку, но в любом случае это должно быть задокументировано (например, см. PyList_New
).
Нужно ли сопоставлять каждому Py_INCREF
значение Py_DECREF
, или должно быть еще одно из одного / другого?
Число в вашем собственном коде может не обязательно совпадать. Число total должно быть сбалансировано, но в самом Python происходят приращения и убывания. Например, все, что возвращает «новую ссылку», уже сделало inc, в то время как все, что «украдет» ссылку, будет делать dec для нее.
Объекты Python, созданные с помощью C API, размещены в стеке в стеке или в куче? (Возможно, что Py_INCREF перераспределяет их в куче, например).
Нет способа создавать объекты через C API в стеке. В C API есть только функции, которые возвращают указатели на объекты.
Большинство этих объектов расположены в куче. Некоторые на самом деле находятся в статической памяти.
Но ваш код все равно не должен волновать. Вы никогда не размещаете и не удаляете их; они распределяются в PySpam_New
и аналогичных функциях и освобождают себя, когда вы Py_DECREF
переводите их в 0, поэтому вам не важно, где они находятся.
(Исключением являются константы, к которым вы можете обращаться через их глобальные имена, например Py_None
. Те, что, как вы знаете, находятся в статическом хранилище.)
Нужно ли делать что-то особенное с объектами Python, созданными в коде C, прежде чем передавать их в код Python?
номер
Что если код Python переживает код C, создавший объекты Python?
Я не уверен, что вы подразумеваете под "переживанием" здесь. Ваш модуль расширения не будет выгружен, в то время как любые объекты зависят от его кода. (На самом деле, по крайней мере, до 3.8 ваш модуль, вероятно, никогда не будет выгружен до завершения работы.)
Если вы просто имеете в виду функцию, которая _New
возвращает объект, это не проблема. Вы должны очень далеко уйти от размещения любых объектов Python в стеке. И нет никакого способа передать такие вещи, как массив объектов C или строку C, в код Python, не преобразовав их в набор объектов Python, или байты Python или str. Есть несколько случаев, когда, например, вы могли бы сохранить указатель на что-либо в стеке в PyCapsule
и передать это - но это то же самое, что и в любой программе на C, и ... просто не делайте этого.
Наконец, я понимаю, что в Python есть счетчик ссылок и сборщик мусора
Сборщик мусора - просто прерыватель цикла. Если у вас есть объекты, которые поддерживают друг друга с помощью ссылочного цикла, вы можете положиться на GC. Но если вы пропустили ссылки на объект, GC никогда не очистит его.