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

Reply via email to