• 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     PyObject_GC_UnTrack(self);
50     Noddy_clear(self);
51     Py_TYPE(self)->tp_free((PyObject*)self);
52 }
53 
54 static PyObject *
Noddy_new(PyTypeObject * type,PyObject * args,PyObject * kwds)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) {
61         self->first = PyString_FromString("");
62         if (self->first == NULL) {
63             Py_DECREF(self);
64             return NULL;
65         }
66 
67         self->last = PyString_FromString("");
68         if (self->last == NULL) {
69             Py_DECREF(self);
70             return NULL;
71         }
72 
73         self->number = 0;
74     }
75 
76     return (PyObject *)self;
77 }
78 
79 static int
Noddy_init(Noddy * self,PyObject * args,PyObject * kwds)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 
86     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
87                                       &first, &last,
88                                       &self->number))
89         return -1;
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 *
Noddy_name(Noddy * self)120 Noddy_name(Noddy* self)
121 {
122     static PyObject *format = NULL;
123     PyObject *args, *result;
124 
125     if (format == NULL) {
126         format = PyString_FromString("%s %s");
127         if (format == NULL)
128             return NULL;
129     }
130 
131     if (self->first == NULL) {
132         PyErr_SetString(PyExc_AttributeError, "first");
133         return NULL;
134     }
135 
136     if (self->last == NULL) {
137         PyErr_SetString(PyExc_AttributeError, "last");
138         return NULL;
139     }
140 
141     args = Py_BuildValue("OO", self->first, self->last);
142     if (args == NULL)
143         return NULL;
144 
145     result = PyString_Format(format, args);
146     Py_DECREF(args);
147 
148     return result;
149 }
150 
151 static PyMethodDef Noddy_methods[] = {
152     {"name", (PyCFunction)Noddy_name, METH_NOARGS,
153      "Return the name, combining the first and last name"
154     },
155     {NULL}  /* Sentinel */
156 };
157 
158 static PyTypeObject NoddyType = {
159     PyVarObject_HEAD_INIT(NULL, 0)
160     "noddy.Noddy",             /* tp_name */
161     sizeof(Noddy),             /* tp_basicsize */
162     0,                         /* tp_itemsize */
163     (destructor)Noddy_dealloc, /* tp_dealloc */
164     0,                         /* tp_print */
165     0,                         /* tp_getattr */
166     0,                         /* tp_setattr */
167     0,                         /* tp_compare */
168     0,                         /* tp_repr */
169     0,                         /* tp_as_number */
170     0,                         /* tp_as_sequence */
171     0,                         /* tp_as_mapping */
172     0,                         /* tp_hash */
173     0,                         /* tp_call */
174     0,                         /* tp_str */
175     0,                         /* tp_getattro */
176     0,                         /* tp_setattro */
177     0,                         /* tp_as_buffer */
178     Py_TPFLAGS_DEFAULT |
179         Py_TPFLAGS_BASETYPE |
180         Py_TPFLAGS_HAVE_GC,    /* tp_flags */
181     "Noddy objects",           /* tp_doc */
182     (traverseproc)Noddy_traverse,   /* tp_traverse */
183     (inquiry)Noddy_clear,           /* tp_clear */
184     0,                         /* tp_richcompare */
185     0,                         /* tp_weaklistoffset */
186     0,                         /* tp_iter */
187     0,                         /* tp_iternext */
188     Noddy_methods,             /* tp_methods */
189     Noddy_members,             /* tp_members */
190     0,                         /* tp_getset */
191     0,                         /* tp_base */
192     0,                         /* tp_dict */
193     0,                         /* tp_descr_get */
194     0,                         /* tp_descr_set */
195     0,                         /* tp_dictoffset */
196     (initproc)Noddy_init,      /* tp_init */
197     0,                         /* tp_alloc */
198     Noddy_new,                 /* tp_new */
199 };
200 
201 static PyMethodDef module_methods[] = {
202     {NULL}  /* Sentinel */
203 };
204 
205 #ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
206 #define PyMODINIT_FUNC void
207 #endif
208 PyMODINIT_FUNC
initnoddy4(void)209 initnoddy4(void)
210 {
211     PyObject* m;
212 
213     if (PyType_Ready(&NoddyType) < 0)
214         return;
215 
216     m = Py_InitModule3("noddy4", module_methods,
217                        "Example module that creates an extension type.");
218 
219     if (m == NULL)
220         return;
221 
222     Py_INCREF(&NoddyType);
223     PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType);
224 }
225