1414   This module roughly corresponds to:: 
1515
1616      class Xxo: 
17-          """A class that explicitly stores attributes in an internal dict""" 
17+          """A class that explicitly stores attributes in an internal dict 
18+          (to simulate custom attribute handling). 
19+          """ 
1820
1921          def __init__(self): 
2022              # In the C class, "_x_attr" is not accessible from Python code 
@@ -85,13 +87,16 @@ typedef struct {
8587// Instance state 
8688typedef  struct  {
8789    PyObject_HEAD 
88-     PyObject             * x_attr ;           /* Attributes dictionary */ 
90+     PyObject             * x_attr ;           /* Attributes dictionary. 
91+                                             * May be NULL, which acts as an 
92+                                             * empty dict. 
93+                                             */ 
8994    char                 x_buffer [BUFSIZE ]; /* buffer for Py_buffer */ 
9095    Py_ssize_t           x_exports ;         /* how many buffer are exported */ 
9196} XxoObject ;
9297
9398#define  XxoObject_CAST (op )  ((XxoObject *)(op))
94- // XXX: no good way to do this yet  
99+ // TODO: full support for type-checking was added in 3.14 (Py_tp_token)  
95100// #define XxoObject_Check(v)      Py_IS_TYPE(v, Xxo_Type) 
96101
97102static  XxoObject  * 
@@ -112,8 +117,13 @@ newXxoObject(PyObject *module)
112117    return  self ;
113118}
114119
115- /* Xxo finalization */ 
120+ /* Xxo finalization. 
121+  * 
122+  * Types that store references to other PyObjects generally need to implement 
123+  * the GC slots: traverse, clear, dealloc, and (optionally) finalize. 
124+  */ 
116125
126+ // traverse: Visit all references from an object, including its type 
117127static  int 
118128Xxo_traverse (PyObject  * op , visitproc  visit , void  * arg )
119129{
@@ -126,6 +136,7 @@ Xxo_traverse(PyObject *op, visitproc visit, void *arg)
126136    return  0 ;
127137}
128138
139+ // clear: drop references in order to break all reference cycles 
129140static  int 
130141Xxo_clear (PyObject  * op )
131142{
@@ -134,13 +145,16 @@ Xxo_clear(PyObject *op)
134145    return  0 ;
135146}
136147
148+ // finalize: like clear, but should leave the object in a consistent state. 
149+ // Equivalent to `__del__` in Python. 
137150static  void 
138151Xxo_finalize (PyObject  * op )
139152{
140153    XxoObject  * self  =  XxoObject_CAST (op );
141154    Py_CLEAR (self -> x_attr );
142155}
143156
157+ // dealloc: drop all remaining references and free memory 
144158static  void 
145159Xxo_dealloc (PyObject  * self )
146160{
@@ -155,6 +169,7 @@ Xxo_dealloc(PyObject *self)
155169
156170/* Xxo attribute handling */ 
157171
172+ // Get an attribute. 
158173static  PyObject  * 
159174Xxo_getattro (PyObject  * op , PyObject  * name )
160175{
@@ -168,9 +183,12 @@ Xxo_getattro(PyObject *op, PyObject *name)
168183            return  NULL ;
169184        }
170185    }
186+     // Fall back to generic implementation (this handles special attributes, 
187+     // raising AttributeError, etc.) 
171188    return  PyObject_GenericGetAttr (op , name );
172189}
173190
191+ // Set or delete an attribute. 
174192static  int 
175193Xxo_setattro (PyObject  * op , PyObject  * name , PyObject  * v )
176194{
@@ -198,7 +216,9 @@ Xxo_setattro(PyObject *op, PyObject *name, PyObject *v)
198216    }
199217}
200218
201- /* Xxo methods */ 
219+ /* Xxo methods: C functions plus a PyMethodDef array that lists them and 
220+  * specifies metadata. 
221+  */ 
202222
203223static  PyObject  * 
204224Xxo_demo (PyObject  * op , PyTypeObject  * defining_class ,
@@ -234,7 +254,10 @@ static PyMethodDef Xxo_methods[] = {
234254    {NULL ,              NULL }           /* sentinel */ 
235255};
236256
237- /* Xxo buffer interface */ 
257+ /* Xxo buffer interface: C functions later referenced from PyType_Slot array. 
258+  * Other interfaces (e.g. for sequence-like or number-like types) are defined 
259+  * similarly. 
260+  */ 
238261
239262static  int 
240263Xxo_getbuffer (PyObject  * op , Py_buffer  * view , int  flags )
@@ -300,6 +323,7 @@ static PyType_Spec Xxo_Type_spec = {
300323/* Str type definition*/ 
301324
302325static  PyType_Slot  Str_Type_slots [] =  {
326+     // slots array intentionally kept empty 
303327    {0 , 0 },  /* sentinel */ 
304328};
305329
@@ -400,12 +424,32 @@ xx_modexec(PyObject *m)
400424}
401425
402426static  PyModuleDef_Slot  xx_slots [] =  {
427+ 
428+     /* exec function to initialize the module (called as part of import 
429+      * after the object was added to sys.modules) 
430+      */ 
403431    {Py_mod_exec , xx_modexec },
432+ 
433+     /* Signal that this module supports being loaded in multiple interpreters 
434+      * with separate GILs (global interpreter locks). 
435+      * See "Isolating Extension Modules" on how to prepare a module for this: 
436+      *   https://docs.python.org/3/howto/isolating-extensions.html 
437+      */ 
404438    {Py_mod_multiple_interpreters , Py_MOD_PER_INTERPRETER_GIL_SUPPORTED },
439+ 
440+     /* Signal that this module does not rely on the GIL for its own needs. 
441+      * Without this slot, free-threaded builds of CPython will enable 
442+      * the GIL when this module is loaded. 
443+      */ 
405444    {Py_mod_gil , Py_MOD_GIL_NOT_USED },
445+ 
406446    {0 , NULL }
407447};
408448
449+ // Module finalization: modules that hold references in their module state 
450+ // need to implement the fullowing GC hooks. They're similar to the ones for 
451+ // types (see "Xxo finalization"). 
452+ 
409453static  int 
410454xx_traverse (PyObject  * module , visitproc  visit , void  * arg )
411455{
@@ -444,7 +488,9 @@ static struct PyModuleDef xxmodule = {
444488};
445489
446490
447- /* Export function for the module (*must* be called PyInit_xx) */ 
491+ /* Export function for the module. *Must* be called PyInit_xx; usually it is 
492+  * the only non-`static` object in a module definition. 
493+  */ 
448494
449495PyMODINIT_FUNC 
450496PyInit_xxlimited (void )
0 commit comments