• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Noddy_traverse(Noddy * self,visitproc visit,void * arg)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 
30 static int
Noddy_clear(Noddy * self)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
Noddy_dealloc(Noddy * self)47 Noddy_dealloc(Noddy* self)
48 {
49     Noddy_clear(self);
50     Py_TYPE(self)->tp_free((PyObject*)self);
51 }
52 
53 static PyObject *
Noddy_new(PyTypeObject * type,PyObject * args,PyObject * kwds)54 Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
55 {
56     Noddy *self;
57 
58     self = (Noddy *)type->tp_alloc(type, 0);
59     if (self != NULL) {
60         self->first = PyUnicode_FromString("");
61         if (self->first == NULL) {
62             Py_DECREF(self);
63             return NULL;
64         }
65 
66         self->last = PyUnicode_FromString("");
67         if (self->last == NULL) {
68             Py_DECREF(self);
69             return NULL;
70         }
71 
72         self->number = 0;
73     }
74 
75     return (PyObject *)self;
76 }
77 
78 static int
Noddy_init(Noddy * self,PyObject * args,PyObject * kwds)79 Noddy_init(Noddy *self, PyObject *args, PyObject *kwds)
80 {
81     PyObject *first=NULL, *last=NULL, *tmp;
82 
83     static char *kwlist[] = {"first", "last", "number", NULL};
84 
85     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
86                                       &first, &last,
87                                       &self->number))
88         return -1;
89 
90     if (first) {
91         tmp = self->first;
92         Py_INCREF(first);
93         self->first = first;
94         Py_XDECREF(tmp);
95     }
96 
97     if (last) {
98         tmp = self->last;
99         Py_INCREF(last);
100         self->last = last;
101         Py_XDECREF(tmp);
102     }
103 
104     return 0;
105 }
106 
107 
108 static PyMemberDef Noddy_members[] = {
109     {"first", T_OBJECT_EX, offsetof(Noddy, first), 0,
110      "first name"},
111     {"last", T_OBJECT_EX, offsetof(Noddy, last), 0,
112      "last name"},
113     {"number", T_INT, offsetof(Noddy, number), 0,
114      "noddy number"},
115     {NULL}  /* Sentinel */
116 };
117 
118 static PyObject *
Noddy_name(Noddy * self)119 Noddy_name(Noddy* self)
120 {
121     if (self->first == NULL) {
122         PyErr_SetString(PyExc_AttributeError, "first");
123         return NULL;
124     }
125 
126     if (self->last == NULL) {
127         PyErr_SetString(PyExc_AttributeError, "last");
128         return NULL;
129     }
130 
131     return PyUnicode_FromFormat("%S %S", self->first, self->last);
132 }
133 
134 static PyMethodDef Noddy_methods[] = {
135     {"name", (PyCFunction)Noddy_name, METH_NOARGS,
136      "Return the name, combining the first and last name"
137     },
138     {NULL}  /* Sentinel */
139 };
140 
141 static PyTypeObject NoddyType = {
142     PyVarObject_HEAD_INIT(NULL, 0)
143     "noddy.Noddy",             /* tp_name */
144     sizeof(Noddy),             /* tp_basicsize */
145     0,                         /* tp_itemsize */
146     (destructor)Noddy_dealloc, /* tp_dealloc */
147     0,                         /* tp_print */
148     0,                         /* tp_getattr */
149     0,                         /* tp_setattr */
150     0,                         /* tp_reserved */
151     0,                         /* tp_repr */
152     0,                         /* tp_as_number */
153     0,                         /* tp_as_sequence */
154     0,                         /* tp_as_mapping */
155     0,                         /* tp_hash  */
156     0,                         /* tp_call */
157     0,                         /* tp_str */
158     0,                         /* tp_getattro */
159     0,                         /* tp_setattro */
160     0,                         /* tp_as_buffer */
161     Py_TPFLAGS_DEFAULT |
162         Py_TPFLAGS_BASETYPE |
163         Py_TPFLAGS_HAVE_GC,    /* tp_flags */
164     "Noddy objects",           /* tp_doc */
165     (traverseproc)Noddy_traverse,   /* tp_traverse */
166     (inquiry)Noddy_clear,           /* tp_clear */
167     0,                         /* tp_richcompare */
168     0,                         /* tp_weaklistoffset */
169     0,                         /* tp_iter */
170     0,                         /* tp_iternext */
171     Noddy_methods,             /* tp_methods */
172     Noddy_members,             /* tp_members */
173     0,                         /* tp_getset */
174     0,                         /* tp_base */
175     0,                         /* tp_dict */
176     0,                         /* tp_descr_get */
177     0,                         /* tp_descr_set */
178     0,                         /* tp_dictoffset */
179     (initproc)Noddy_init,      /* tp_init */
180     0,                         /* tp_alloc */
181     Noddy_new,                 /* tp_new */
182 };
183 
184 static PyModuleDef noddy4module = {
185     PyModuleDef_HEAD_INIT,
186     "noddy4",
187     "Example module that creates an extension type.",
188     -1,
189     NULL, NULL, NULL, NULL, NULL
190 };
191 
192 PyMODINIT_FUNC
PyInit_noddy4(void)193 PyInit_noddy4(void)
194 {
195     PyObject* m;
196 
197     if (PyType_Ready(&NoddyType) < 0)
198         return NULL;
199 
200     m = PyModule_Create(&noddy4module);
201     if (m == NULL)
202         return NULL;
203 
204     Py_INCREF(&NoddyType);
205     PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType);
206     return m;
207 }
208