1#define PY_SSIZE_T_CLEAN 2#include <Python.h> 3#include "structmember.h" 4 5typedef struct { 6 PyObject_HEAD 7 PyObject *first; /* first name */ 8 PyObject *last; /* last name */ 9 int number; 10} CustomObject; 11 12static void 13Custom_dealloc(CustomObject *self) 14{ 15 Py_XDECREF(self->first); 16 Py_XDECREF(self->last); 17 Py_TYPE(self)->tp_free((PyObject *) self); 18} 19 20static PyObject * 21Custom_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 41static int 42Custom_init(CustomObject *self, PyObject *args, PyObject *kwds) 43{ 44 static char *kwlist[] = {"first", "last", "number", NULL}; 45 PyObject *first = NULL, *last = NULL, *tmp; 46 47 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist, 48 &first, &last, 49 &self->number)) 50 return -1; 51 52 if (first) { 53 tmp = self->first; 54 Py_INCREF(first); 55 self->first = first; 56 Py_DECREF(tmp); 57 } 58 if (last) { 59 tmp = self->last; 60 Py_INCREF(last); 61 self->last = last; 62 Py_DECREF(tmp); 63 } 64 return 0; 65} 66 67static PyMemberDef Custom_members[] = { 68 {"number", T_INT, offsetof(CustomObject, number), 0, 69 "custom number"}, 70 {NULL} /* Sentinel */ 71}; 72 73static PyObject * 74Custom_getfirst(CustomObject *self, void *closure) 75{ 76 Py_INCREF(self->first); 77 return self->first; 78} 79 80static int 81Custom_setfirst(CustomObject *self, PyObject *value, void *closure) 82{ 83 PyObject *tmp; 84 if (value == NULL) { 85 PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); 86 return -1; 87 } 88 if (!PyUnicode_Check(value)) { 89 PyErr_SetString(PyExc_TypeError, 90 "The first attribute value must be a string"); 91 return -1; 92 } 93 tmp = self->first; 94 Py_INCREF(value); 95 self->first = value; 96 Py_DECREF(tmp); 97 return 0; 98} 99 100static PyObject * 101Custom_getlast(CustomObject *self, void *closure) 102{ 103 Py_INCREF(self->last); 104 return self->last; 105} 106 107static int 108Custom_setlast(CustomObject *self, PyObject *value, void *closure) 109{ 110 PyObject *tmp; 111 if (value == NULL) { 112 PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); 113 return -1; 114 } 115 if (!PyUnicode_Check(value)) { 116 PyErr_SetString(PyExc_TypeError, 117 "The last attribute value must be a string"); 118 return -1; 119 } 120 tmp = self->last; 121 Py_INCREF(value); 122 self->last = value; 123 Py_DECREF(tmp); 124 return 0; 125} 126 127static 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 135static PyObject * 136Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored)) 137{ 138 return PyUnicode_FromFormat("%S %S", self->first, self->last); 139} 140 141static 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 148static PyTypeObject CustomType = { 149 PyVarObject_HEAD_INIT(NULL, 0) 150 .tp_name = "custom3.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, 155 .tp_new = Custom_new, 156 .tp_init = (initproc) Custom_init, 157 .tp_dealloc = (destructor) Custom_dealloc, 158 .tp_members = Custom_members, 159 .tp_methods = Custom_methods, 160 .tp_getset = Custom_getsetters, 161}; 162 163static PyModuleDef custommodule = { 164 PyModuleDef_HEAD_INIT, 165 .m_name = "custom3", 166 .m_doc = "Example module that creates an extension type.", 167 .m_size = -1, 168}; 169 170PyMODINIT_FUNC 171PyInit_custom3(void) 172{ 173 PyObject *m; 174 if (PyType_Ready(&CustomType) < 0) 175 return NULL; 176 177 m = PyModule_Create(&custommodule); 178 if (m == NULL) 179 return NULL; 180 181 Py_INCREF(&CustomType); 182 if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) { 183 Py_DECREF(&CustomType); 184 Py_DECREF(m); 185 return NULL; 186 } 187 188 return m; 189} 190