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, "|OOi", kwlist,
      48                                       &first, &last,
      49                                       &self->number))
      50          return -1;
      51  
      52      if (first) {
      53          Py_XSETREF(self->first, Py_NewRef(first));
      54      }
      55      if (last) {
      56          Py_XSETREF(self->last, Py_NewRef(last));
      57      }
      58      return 0;
      59  }
      60  
      61  static PyMemberDef Custom_members[] = {
      62      {"first", Py_T_OBJECT_EX, offsetof(CustomObject, first), 0,
      63       "first name"},
      64      {"last", Py_T_OBJECT_EX, offsetof(CustomObject, last), 0,
      65       "last name"},
      66      {"number", Py_T_INT, offsetof(CustomObject, number), 0,
      67       "custom number"},
      68      {NULL}  /* Sentinel */
      69  };
      70  
      71  static PyObject *
      72  Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
      73  {
      74      if (self->first == NULL) {
      75          PyErr_SetString(PyExc_AttributeError, "first");
      76          return NULL;
      77      }
      78      if (self->last == NULL) {
      79          PyErr_SetString(PyExc_AttributeError, "last");
      80          return NULL;
      81      }
      82      return PyUnicode_FromFormat("%S %S", self->first, self->last);
      83  }
      84  
      85  static PyMethodDef Custom_methods[] = {
      86      {"name", (PyCFunction) Custom_name, METH_NOARGS,
      87       "Return the name, combining the first and last name"
      88      },
      89      {NULL}  /* Sentinel */
      90  };
      91  
      92  static PyTypeObject CustomType = {
      93      .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
      94      .tp_name = "custom2.Custom",
      95      .tp_doc = PyDoc_STR("Custom objects"),
      96      .tp_basicsize = sizeof(CustomObject),
      97      .tp_itemsize = 0,
      98      .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
      99      .tp_new = Custom_new,
     100      .tp_init = (initproc) Custom_init,
     101      .tp_dealloc = (destructor) Custom_dealloc,
     102      .tp_members = Custom_members,
     103      .tp_methods = Custom_methods,
     104  };
     105  
     106  static PyModuleDef custommodule = {
     107      .m_base =PyModuleDef_HEAD_INIT,
     108      .m_name = "custom2",
     109      .m_doc = "Example module that creates an extension type.",
     110      .m_size = -1,
     111  };
     112  
     113  PyMODINIT_FUNC
     114  PyInit_custom2(void)
     115  {
     116      PyObject *m;
     117      if (PyType_Ready(&CustomType) < 0)
     118          return NULL;
     119  
     120      m = PyModule_Create(&custommodule);
     121      if (m == NULL)
     122          return NULL;
     123  
     124      if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
     125          Py_DECREF(m);
     126          return NULL;
     127      }
     128  
     129      return m;
     130  }