1 #include <Python.h> 2 #include "structmember.h" 3 4 typedef struct { 5 PyObject_HEAD 6 PyObject *first; 7 PyObject *last; 8 int number; 9 } Noddy; 10 11 static void 12 Noddy_dealloc(Noddy* self) 13 { 14 Py_XDECREF(self->first); 15 Py_XDECREF(self->last); 16 Py_TYPE(self)->tp_free((PyObject*)self); 17 } 18 19 static PyObject * 20 Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 21 { 22 Noddy *self; 23 24 self = (Noddy *)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 32 self->last = PyUnicode_FromString(""); 33 if (self->last == NULL) { 34 Py_DECREF(self); 35 return NULL; 36 } 37 38 self->number = 0; 39 } 40 41 return (PyObject *)self; 42 } 43 44 static int 45 Noddy_init(Noddy *self, PyObject *args, PyObject *kwds) 46 { 47 PyObject *first=NULL, *last=NULL, *tmp; 48 49 static char *kwlist[] = {"first", "last", "number", NULL}; 50 51 if (! PyArg_ParseTupleAndKeywords(args, kwds, "|SSi", kwlist, 52 &first, &last, 53 &self->number)) 54 return -1; 55 56 if (first) { 57 tmp = self->first; 58 Py_INCREF(first); 59 self->first = first; 60 Py_DECREF(tmp); 61 } 62 63 if (last) { 64 tmp = self->last; 65 Py_INCREF(last); 66 self->last = last; 67 Py_DECREF(tmp); 68 } 69 70 return 0; 71 } 72 73 static PyMemberDef Noddy_members[] = { 74 {"number", T_INT, offsetof(Noddy, number), 0, 75 "noddy number"}, 76 {NULL} /* Sentinel */ 77 }; 78 79 static PyObject * 80 Noddy_getfirst(Noddy *self, void *closure) 81 { 82 Py_INCREF(self->first); 83 return self->first; 84 } 85 86 static int 87 Noddy_setfirst(Noddy *self, PyObject *value, void *closure) 88 { 89 if (value == NULL) { 90 PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); 91 return -1; 92 } 93 94 if (! PyUnicode_Check(value)) { 95 PyErr_SetString(PyExc_TypeError, 96 "The first attribute value must be a string"); 97 return -1; 98 } 99 100 Py_DECREF(self->first); 101 Py_INCREF(value); 102 self->first = value; 103 104 return 0; 105 } 106 107 static PyObject * 108 Noddy_getlast(Noddy *self, void *closure) 109 { 110 Py_INCREF(self->last); 111 return self->last; 112 } 113 114 static int 115 Noddy_setlast(Noddy *self, PyObject *value, void *closure) 116 { 117 if (value == NULL) { 118 PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); 119 return -1; 120 } 121 122 if (! PyUnicode_Check(value)) { 123 PyErr_SetString(PyExc_TypeError, 124 "The last attribute value must be a string"); 125 return -1; 126 } 127 128 Py_DECREF(self->last); 129 Py_INCREF(value); 130 self->last = value; 131 132 return 0; 133 } 134 135 static PyGetSetDef Noddy_getseters[] = { 136 {"first", 137 (getter)Noddy_getfirst, (setter)Noddy_setfirst, 138 "first name", 139 NULL}, 140 {"last", 141 (getter)Noddy_getlast, (setter)Noddy_setlast, 142 "last name", 143 NULL}, 144 {NULL} /* Sentinel */ 145 }; 146 147 static PyObject * 148 Noddy_name(Noddy* self) 149 { 150 return PyUnicode_FromFormat("%S %S", self->first, self->last); 151 } 152 153 static PyMethodDef Noddy_methods[] = { 154 {"name", (PyCFunction)Noddy_name, METH_NOARGS, 155 "Return the name, combining the first and last name" 156 }, 157 {NULL} /* Sentinel */ 158 }; 159 160 static PyTypeObject NoddyType = { 161 PyVarObject_HEAD_INIT(NULL, 0) 162 "noddy.Noddy", /* tp_name */ 163 sizeof(Noddy), /* tp_basicsize */ 164 0, /* tp_itemsize */ 165 (destructor)Noddy_dealloc, /* tp_dealloc */ 166 0, /* tp_print */ 167 0, /* tp_getattr */ 168 0, /* tp_setattr */ 169 0, /* tp_reserved */ 170 0, /* tp_repr */ 171 0, /* tp_as_number */ 172 0, /* tp_as_sequence */ 173 0, /* tp_as_mapping */ 174 0, /* tp_hash */ 175 0, /* tp_call */ 176 0, /* tp_str */ 177 0, /* tp_getattro */ 178 0, /* tp_setattro */ 179 0, /* tp_as_buffer */ 180 Py_TPFLAGS_DEFAULT | 181 Py_TPFLAGS_BASETYPE, /* tp_flags */ 182 "Noddy objects", /* tp_doc */ 183 0, /* tp_traverse */ 184 0, /* tp_clear */ 185 0, /* tp_richcompare */ 186 0, /* tp_weaklistoffset */ 187 0, /* tp_iter */ 188 0, /* tp_iternext */ 189 Noddy_methods, /* tp_methods */ 190 Noddy_members, /* tp_members */ 191 Noddy_getseters, /* tp_getset */ 192 0, /* tp_base */ 193 0, /* tp_dict */ 194 0, /* tp_descr_get */ 195 0, /* tp_descr_set */ 196 0, /* tp_dictoffset */ 197 (initproc)Noddy_init, /* tp_init */ 198 0, /* tp_alloc */ 199 Noddy_new, /* tp_new */ 200 }; 201 202 static PyModuleDef noddy3module = { 203 PyModuleDef_HEAD_INIT, 204 "noddy3", 205 "Example module that creates an extension type.", 206 -1, 207 NULL, NULL, NULL, NULL, NULL 208 }; 209 210 PyMODINIT_FUNC 211 PyInit_noddy3(void) 212 { 213 PyObject* m; 214 215 if (PyType_Ready(&NoddyType) < 0) 216 return NULL; 217 218 m = PyModule_Create(&noddy3module); 219 if (m == NULL) 220 return NULL; 221 222 Py_INCREF(&NoddyType); 223 PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType); 224 return m; 225 } 226