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