Thanks for your reply jason. Your reply does give me hints and then I
read more code and find maybe you are wrong in some points.
I think the meaning of Py_INCREF a static type object is to prevent it
from being deallocated when it is Py_DECREFed somehow later. Just as you
said, it may be somehow deallocated when using.
NoddyType is a static struct so I don't think it lives on Python's heap
and deallocating it is a wrong action. Just as I mentioned, type_dealloc
seems to only deallocated HEAPTYPE. And by the way, when NoddyType is
created, it has a reference count 1 with PyVarObject_HEAD_INIT. So if I
don't Py_INCREF it, when it is somehow Py_DECREDed later, it will reach
reference count 0 and fail the assert in type_dealloc. If it is
Py_INCREFed, just like the module holds a reference to it, it will at
least have a reference count 1 and never reach 0.
On 11/13/2015 02:52 AM, Jason Swails wrote:
On Thu, Nov 12, 2015 at 3:05 AM, Xiang Zhang <18518281...@126.com
<mailto:18518281...@126.com>> wrote:
Recently I am learning Python C API.
When I read the tutorial
<https://docs.python.org/3/extending/newtypes.html#the-basics>,
defining new types, I feel confused. After
PyType_Ready(&noddy_NoddyType) comes Py_INCREF(&noddy_NoddyType).
Actually noddy_NoddyType is a static struct so I don't understand
why I need to Py_INCREF it. Since it's Py_INCREFed, does it mean
sometimes we also need to Py_DECREF it? But then it seems that
type_dealloc will be invoked and it will fail
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
It is a module attribute, so when the module is imported it has to
have a single reference (the reference *in* the module). If you don't
INCREF it, then it will have a refcount of 0, and immediately be ready
for garbage collection. So if you try to use the type from the
module, you could get a segfault because it's trying to use an object
(type definition) that was already destroyed.
Note that you don't *always* have to INCREF objects after you create
them in C. Some macros and function do that for you. And in some
cases, all you want or need is a borrowed reference. In those cases,
Py_INCREF is unnecessary.
The DECREF will be done when it's normally done in Python. If you do
something like
import noddy
del noddy.NoddyType
All that's really doing is removing NoddyType from the noddy
namespace and Py_DECREFing it. Alternatively, doing
import noddy
noddy.NoddyType = 10 # rebind the name
Then the original object NoddyType was pointing to will be DECREFed
and NoddyType will point to an object taking the value of 10.
HTH,
Jason
--
https://mail.python.org/mailman/listinfo/python-list