(root)/
Python-3.12.0/
Doc/
includes/
newtypes/
custom4.c
       1  #define PY_SSIZE_T_CLEAN
       2  #include <Python.h>
       3  #include <stddef.h> /* for offsetof() */
       4  
       5  typedef struct {
       6      PyObject_HEAD
       7      PyObject *first; /* first name */
       8      PyObject *last;  /* last name */
       9      int number;
      10  } CustomObject;
      11  
      12  static int
      13  Custom_traverse(CustomObject *self, visitproc visit, void *arg)
      14  {
      15      Py_VISIT(self->first);
      16      Py_VISIT(self->last);
      17      return 0;
      18  }
      19  
      20  static int
      21  Custom_clear(CustomObject *self)
      22  {
      23      Py_CLEAR(self->first);
      24      Py_CLEAR(self->last);
      25      return 0;
      26  }
      27  
      28  static void
      29  Custom_dealloc(CustomObject *self)
      30  {
      31      PyObject_GC_UnTrack(self);
      32      Custom_clear(self);
      33      Py_TYPE(self)->tp_free((PyObject *) self);
      34  }
      35  
      36  static PyObject *
      37  Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
      38  {
      39      CustomObject *self;
      40      self = (CustomObject *) type->tp_alloc(type, 0);
      41      if (self != NULL) {
      42          self->first = PyUnicode_FromString("");
      43          if (self->first == NULL) {
      44              Py_DECREF(self);
      45              return NULL;
      46          }
      47          self->last = PyUnicode_FromString("");
      48          if (self->last == NULL) {
      49              Py_DECREF(self);
      50              return NULL;
      51          }
      52          self->number = 0;
      53      }
      54      return (PyObject *) self;
      55  }
      56  
      57  static int
      58  Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
      59  {
      60      static char *kwlist[] = {"first", "last", "number", NULL};
      61      PyObject *first = NULL, *last = NULL;
      62  
      63      if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
      64                                       &first, &last,
      65                                       &self->number))
      66          return -1;
      67  
      68      if (first) {
      69          Py_SETREF(self->first, Py_NewRef(first));
      70      }
      71      if (last) {
      72          Py_SETREF(self->last, Py_NewRef(last));
      73      }
      74      return 0;
      75  }
      76  
      77  static PyMemberDef Custom_members[] = {
      78      {"number", Py_T_INT, offsetof(CustomObject, number), 0,
      79       "custom number"},
      80      {NULL}  /* Sentinel */
      81  };
      82  
      83  static PyObject *
      84  Custom_getfirst(CustomObject *self, void *closure)
      85  {
      86      return Py_NewRef(self->first);
      87  }
      88  
      89  static int
      90  Custom_setfirst(CustomObject *self, PyObject *value, void *closure)
      91  {
      92      if (value == NULL) {
      93          PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
      94          return -1;
      95      }
      96      if (!PyUnicode_Check(value)) {
      97          PyErr_SetString(PyExc_TypeError,
      98                          "The first attribute value must be a string");
      99          return -1;
     100      }
     101      Py_XSETREF(self->first, Py_NewRef(value));
     102      return 0;
     103  }
     104  
     105  static PyObject *
     106  Custom_getlast(CustomObject *self, void *closure)
     107  {
     108      return Py_NewRef(self->last);
     109  }
     110  
     111  static int
     112  Custom_setlast(CustomObject *self, PyObject *value, void *closure)
     113  {
     114      if (value == NULL) {
     115          PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
     116          return -1;
     117      }
     118      if (!PyUnicode_Check(value)) {
     119          PyErr_SetString(PyExc_TypeError,
     120                          "The last attribute value must be a string");
     121          return -1;
     122      }
     123      Py_XSETREF(self->last, Py_NewRef(value));
     124      return 0;
     125  }
     126  
     127  static PyGetSetDef Custom_getsetters[] = {
     128      {"first", (getter) Custom_getfirst, (setter) Custom_setfirst,
     129       "first name", NULL},
     130      {"last", (getter) Custom_getlast, (setter) Custom_setlast,
     131       "last name", NULL},
     132      {NULL}  /* Sentinel */
     133  };
     134  
     135  static PyObject *
     136  Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
     137  {
     138      return PyUnicode_FromFormat("%S %S", self->first, self->last);
     139  }
     140  
     141  static PyMethodDef Custom_methods[] = {
     142      {"name", (PyCFunction) Custom_name, METH_NOARGS,
     143       "Return the name, combining the first and last name"
     144      },
     145      {NULL}  /* Sentinel */
     146  };
     147  
     148  static PyTypeObject CustomType = {
     149      .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
     150      .tp_name = "custom4.Custom",
     151      .tp_doc = PyDoc_STR("Custom objects"),
     152      .tp_basicsize = sizeof(CustomObject),
     153      .tp_itemsize = 0,
     154      .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
     155      .tp_new = Custom_new,
     156      .tp_init = (initproc) Custom_init,
     157      .tp_dealloc = (destructor) Custom_dealloc,
     158      .tp_traverse = (traverseproc) Custom_traverse,
     159      .tp_clear = (inquiry) Custom_clear,
     160      .tp_members = Custom_members,
     161      .tp_methods = Custom_methods,
     162      .tp_getset = Custom_getsetters,
     163  };
     164  
     165  static PyModuleDef custommodule = {
     166      .m_base = PyModuleDef_HEAD_INIT,
     167      .m_name = "custom4",
     168      .m_doc = "Example module that creates an extension type.",
     169      .m_size = -1,
     170  };
     171  
     172  PyMODINIT_FUNC
     173  PyInit_custom4(void)
     174  {
     175      PyObject *m;
     176      if (PyType_Ready(&CustomType) < 0)
     177          return NULL;
     178  
     179      m = PyModule_Create(&custommodule);
     180      if (m == NULL)
     181          return NULL;
     182  
     183      if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
     184          Py_DECREF(m);
     185          return NULL;
     186      }
     187  
     188      return m;
     189  }