| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 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 int | 
|  | 12 | Noddy_traverse(Noddy *self, visitproc visit, void *arg) | 
|  | 13 | { | 
|  | 14 | int vret; | 
|  | 15 |  | 
|  | 16 | if (self->first) { | 
|  | 17 | vret = visit(self->first, arg); | 
|  | 18 | if (vret != 0) | 
|  | 19 | return vret; | 
|  | 20 | } | 
|  | 21 | if (self->last) { | 
|  | 22 | vret = visit(self->last, arg); | 
|  | 23 | if (vret != 0) | 
|  | 24 | return vret; | 
|  | 25 | } | 
|  | 26 |  | 
|  | 27 | return 0; | 
|  | 28 | } | 
|  | 29 |  | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 30 | static int | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 31 | Noddy_clear(Noddy *self) | 
|  | 32 | { | 
|  | 33 | PyObject *tmp; | 
|  | 34 |  | 
|  | 35 | tmp = self->first; | 
|  | 36 | self->first = NULL; | 
|  | 37 | Py_XDECREF(tmp); | 
|  | 38 |  | 
|  | 39 | tmp = self->last; | 
|  | 40 | self->last = NULL; | 
|  | 41 | Py_XDECREF(tmp); | 
|  | 42 |  | 
|  | 43 | return 0; | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | static void | 
|  | 47 | Noddy_dealloc(Noddy* self) | 
|  | 48 | { | 
| INADA Naoki | a6296d3 | 2017-08-24 14:55:17 +0900 | [diff] [blame^] | 49 | PyObject_GC_UnTrack(self); | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 50 | Noddy_clear(self); | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 51 | Py_TYPE(self)->tp_free((PyObject*)self); | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 52 | } | 
|  | 53 |  | 
|  | 54 | static PyObject * | 
|  | 55 | Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
|  | 56 | { | 
|  | 57 | Noddy *self; | 
|  | 58 |  | 
|  | 59 | self = (Noddy *)type->tp_alloc(type, 0); | 
|  | 60 | if (self != NULL) { | 
| Neal Norwitz | bed6784 | 2007-10-27 04:00:45 +0000 | [diff] [blame] | 61 | self->first = PyUnicode_FromString(""); | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 62 | if (self->first == NULL) { | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 63 | Py_DECREF(self); | 
|  | 64 | return NULL; | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 65 | } | 
|  | 66 |  | 
| Neal Norwitz | bed6784 | 2007-10-27 04:00:45 +0000 | [diff] [blame] | 67 | self->last = PyUnicode_FromString(""); | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 68 | if (self->last == NULL) { | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 69 | Py_DECREF(self); | 
|  | 70 | return NULL; | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 71 | } | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 72 |  | 
|  | 73 | self->number = 0; | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | return (PyObject *)self; | 
|  | 77 | } | 
|  | 78 |  | 
|  | 79 | static int | 
|  | 80 | Noddy_init(Noddy *self, PyObject *args, PyObject *kwds) | 
|  | 81 | { | 
|  | 82 | PyObject *first=NULL, *last=NULL, *tmp; | 
|  | 83 |  | 
|  | 84 | static char *kwlist[] = {"first", "last", "number", NULL}; | 
|  | 85 |  | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 86 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, | 
|  | 87 | &first, &last, | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 88 | &self->number)) | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 89 | return -1; | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 90 |  | 
|  | 91 | if (first) { | 
|  | 92 | tmp = self->first; | 
|  | 93 | Py_INCREF(first); | 
|  | 94 | self->first = first; | 
|  | 95 | Py_XDECREF(tmp); | 
|  | 96 | } | 
|  | 97 |  | 
|  | 98 | if (last) { | 
|  | 99 | tmp = self->last; | 
|  | 100 | Py_INCREF(last); | 
|  | 101 | self->last = last; | 
|  | 102 | Py_XDECREF(tmp); | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | return 0; | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 |  | 
|  | 109 | static PyMemberDef Noddy_members[] = { | 
|  | 110 | {"first", T_OBJECT_EX, offsetof(Noddy, first), 0, | 
|  | 111 | "first name"}, | 
|  | 112 | {"last", T_OBJECT_EX, offsetof(Noddy, last), 0, | 
|  | 113 | "last name"}, | 
|  | 114 | {"number", T_INT, offsetof(Noddy, number), 0, | 
|  | 115 | "noddy number"}, | 
|  | 116 | {NULL}  /* Sentinel */ | 
|  | 117 | }; | 
|  | 118 |  | 
|  | 119 | static PyObject * | 
|  | 120 | Noddy_name(Noddy* self) | 
|  | 121 | { | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 122 | if (self->first == NULL) { | 
|  | 123 | PyErr_SetString(PyExc_AttributeError, "first"); | 
|  | 124 | return NULL; | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | if (self->last == NULL) { | 
|  | 128 | PyErr_SetString(PyExc_AttributeError, "last"); | 
|  | 129 | return NULL; | 
|  | 130 | } | 
|  | 131 |  | 
| Amaury Forgeot d'Arc | 864741b | 2011-11-06 15:10:48 +0100 | [diff] [blame] | 132 | return PyUnicode_FromFormat("%S %S", self->first, self->last); | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 133 | } | 
|  | 134 |  | 
|  | 135 | static PyMethodDef Noddy_methods[] = { | 
|  | 136 | {"name", (PyCFunction)Noddy_name, METH_NOARGS, | 
|  | 137 | "Return the name, combining the first and last name" | 
|  | 138 | }, | 
|  | 139 | {NULL}  /* Sentinel */ | 
|  | 140 | }; | 
|  | 141 |  | 
|  | 142 | static PyTypeObject NoddyType = { | 
| Georg Brandl | 5133529 | 2009-05-05 07:55:26 +0000 | [diff] [blame] | 143 | PyVarObject_HEAD_INIT(NULL, 0) | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 144 | "noddy.Noddy",             /* tp_name */ | 
|  | 145 | sizeof(Noddy),             /* tp_basicsize */ | 
|  | 146 | 0,                         /* tp_itemsize */ | 
|  | 147 | (destructor)Noddy_dealloc, /* tp_dealloc */ | 
|  | 148 | 0,                         /* tp_print */ | 
|  | 149 | 0,                         /* tp_getattr */ | 
|  | 150 | 0,                         /* tp_setattr */ | 
| Mark Dickinson | 9f98926 | 2009-02-02 21:29:40 +0000 | [diff] [blame] | 151 | 0,                         /* tp_reserved */ | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 152 | 0,                         /* tp_repr */ | 
|  | 153 | 0,                         /* tp_as_number */ | 
|  | 154 | 0,                         /* tp_as_sequence */ | 
|  | 155 | 0,                         /* tp_as_mapping */ | 
|  | 156 | 0,                         /* tp_hash  */ | 
|  | 157 | 0,                         /* tp_call */ | 
|  | 158 | 0,                         /* tp_str */ | 
|  | 159 | 0,                         /* tp_getattro */ | 
|  | 160 | 0,                         /* tp_setattro */ | 
|  | 161 | 0,                         /* tp_as_buffer */ | 
|  | 162 | Py_TPFLAGS_DEFAULT | | 
|  | 163 | Py_TPFLAGS_BASETYPE | | 
|  | 164 | Py_TPFLAGS_HAVE_GC,    /* tp_flags */ | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 165 | "Noddy objects",           /* tp_doc */ | 
|  | 166 | (traverseproc)Noddy_traverse,   /* tp_traverse */ | 
|  | 167 | (inquiry)Noddy_clear,           /* tp_clear */ | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 168 | 0,                         /* tp_richcompare */ | 
|  | 169 | 0,                         /* tp_weaklistoffset */ | 
|  | 170 | 0,                         /* tp_iter */ | 
|  | 171 | 0,                         /* tp_iternext */ | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 172 | Noddy_methods,             /* tp_methods */ | 
|  | 173 | Noddy_members,             /* tp_members */ | 
|  | 174 | 0,                         /* tp_getset */ | 
|  | 175 | 0,                         /* tp_base */ | 
|  | 176 | 0,                         /* tp_dict */ | 
|  | 177 | 0,                         /* tp_descr_get */ | 
|  | 178 | 0,                         /* tp_descr_set */ | 
|  | 179 | 0,                         /* tp_dictoffset */ | 
|  | 180 | (initproc)Noddy_init,      /* tp_init */ | 
|  | 181 | 0,                         /* tp_alloc */ | 
|  | 182 | Noddy_new,                 /* tp_new */ | 
|  | 183 | }; | 
|  | 184 |  | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 185 | static PyModuleDef noddy4module = { | 
|  | 186 | PyModuleDef_HEAD_INIT, | 
|  | 187 | "noddy4", | 
|  | 188 | "Example module that creates an extension type.", | 
|  | 189 | -1, | 
|  | 190 | NULL, NULL, NULL, NULL, NULL | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 191 | }; | 
|  | 192 |  | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 193 | PyMODINIT_FUNC | 
| Eli Bendersky | 47fe5c0 | 2011-08-12 11:40:39 +0300 | [diff] [blame] | 194 | PyInit_noddy4(void) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 195 | { | 
|  | 196 | PyObject* m; | 
|  | 197 |  | 
|  | 198 | if (PyType_Ready(&NoddyType) < 0) | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 199 | return NULL; | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 200 |  | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 201 | m = PyModule_Create(&noddy4module); | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 202 | if (m == NULL) | 
| Georg Brandl | 913b2a3 | 2008-12-05 15:12:15 +0000 | [diff] [blame] | 203 | return NULL; | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 204 |  | 
|  | 205 | Py_INCREF(&NoddyType); | 
|  | 206 | PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType); | 
| Benjamin Peterson | 71e30a0 | 2008-12-24 16:27:25 +0000 | [diff] [blame] | 207 | return m; | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 208 | } |