|
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 |
|
30 static int |
|
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 { |
|
49 Noddy_clear(self); |
|
50 self->ob_type->tp_free((PyObject*)self); |
|
51 } |
|
52 |
|
53 static PyObject * |
|
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 = PyString_FromString(""); |
|
61 if (self->first == NULL) |
|
62 { |
|
63 Py_DECREF(self); |
|
64 return NULL; |
|
65 } |
|
66 |
|
67 self->last = PyString_FromString(""); |
|
68 if (self->last == NULL) |
|
69 { |
|
70 Py_DECREF(self); |
|
71 return NULL; |
|
72 } |
|
73 |
|
74 self->number = 0; |
|
75 } |
|
76 |
|
77 return (PyObject *)self; |
|
78 } |
|
79 |
|
80 static int |
|
81 Noddy_init(Noddy *self, PyObject *args, PyObject *kwds) |
|
82 { |
|
83 PyObject *first=NULL, *last=NULL, *tmp; |
|
84 |
|
85 static char *kwlist[] = {"first", "last", "number", NULL}; |
|
86 |
|
87 if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, |
|
88 &first, &last, |
|
89 &self->number)) |
|
90 return -1; |
|
91 |
|
92 if (first) { |
|
93 tmp = self->first; |
|
94 Py_INCREF(first); |
|
95 self->first = first; |
|
96 Py_XDECREF(tmp); |
|
97 } |
|
98 |
|
99 if (last) { |
|
100 tmp = self->last; |
|
101 Py_INCREF(last); |
|
102 self->last = last; |
|
103 Py_XDECREF(tmp); |
|
104 } |
|
105 |
|
106 return 0; |
|
107 } |
|
108 |
|
109 |
|
110 static PyMemberDef Noddy_members[] = { |
|
111 {"first", T_OBJECT_EX, offsetof(Noddy, first), 0, |
|
112 "first name"}, |
|
113 {"last", T_OBJECT_EX, offsetof(Noddy, last), 0, |
|
114 "last name"}, |
|
115 {"number", T_INT, offsetof(Noddy, number), 0, |
|
116 "noddy number"}, |
|
117 {NULL} /* Sentinel */ |
|
118 }; |
|
119 |
|
120 static PyObject * |
|
121 Noddy_name(Noddy* self) |
|
122 { |
|
123 static PyObject *format = NULL; |
|
124 PyObject *args, *result; |
|
125 |
|
126 if (format == NULL) { |
|
127 format = PyString_FromString("%s %s"); |
|
128 if (format == NULL) |
|
129 return NULL; |
|
130 } |
|
131 |
|
132 if (self->first == NULL) { |
|
133 PyErr_SetString(PyExc_AttributeError, "first"); |
|
134 return NULL; |
|
135 } |
|
136 |
|
137 if (self->last == NULL) { |
|
138 PyErr_SetString(PyExc_AttributeError, "last"); |
|
139 return NULL; |
|
140 } |
|
141 |
|
142 args = Py_BuildValue("OO", self->first, self->last); |
|
143 if (args == NULL) |
|
144 return NULL; |
|
145 |
|
146 result = PyString_Format(format, args); |
|
147 Py_DECREF(args); |
|
148 |
|
149 return result; |
|
150 } |
|
151 |
|
152 static PyMethodDef Noddy_methods[] = { |
|
153 {"name", (PyCFunction)Noddy_name, METH_NOARGS, |
|
154 "Return the name, combining the first and last name" |
|
155 }, |
|
156 {NULL} /* Sentinel */ |
|
157 }; |
|
158 |
|
159 static PyTypeObject NoddyType = { |
|
160 PyObject_HEAD_INIT(NULL) |
|
161 0, /*ob_size*/ |
|
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_compare*/ |
|
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 | Py_TPFLAGS_BASETYPE | 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 |
|
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 } |