1
2 /* Use this file as a template to start implementing a module that
3 also declares object types. All occurrences of 'Xxo' should be changed
4 to something reasonable for your objects. After that, all other
5 occurrences of 'xx' should be changed to something reasonable for your
6 module. If your module is named foo your sourcefile should be named
7 foomodule.c.
8
9 You will probably want to delete all references to 'x_attr' and add
10 your own types of attributes instead. Maybe you want to name your
11 local variables other than 'self'. If your object type is needed in
12 other files, you'll have to create a file "foobarobject.h"; see
13 floatobject.h for an example. */
14
15 /* Xxo objects */
16
17 #include "Python.h"
18
19 static PyObject *ErrorObject;
20
21 typedef struct {
22 PyObject_HEAD
23 PyObject *x_attr; /* Attributes dictionary */
24 } XxoObject;
25
26 static PyObject *Xxo_Type;
27
28 #define XxoObject_Check(v) (Py_TYPE(v) == Xxo_Type)
29
30 static XxoObject *
newXxoObject(PyObject * arg)31 newXxoObject(PyObject *arg)
32 {
33 XxoObject *self;
34 self = PyObject_GC_New(XxoObject, (PyTypeObject*)Xxo_Type);
35 if (self == NULL)
36 return NULL;
37 self->x_attr = NULL;
38 return self;
39 }
40
41 /* Xxo methods */
42
43 static int
Xxo_traverse(XxoObject * self,visitproc visit,void * arg)44 Xxo_traverse(XxoObject *self, visitproc visit, void *arg)
45 {
46 Py_VISIT(self->x_attr);
47 return 0;
48 }
49
50 static void
Xxo_finalize(XxoObject * self)51 Xxo_finalize(XxoObject *self)
52 {
53 Py_CLEAR(self->x_attr);
54 }
55
56 static PyObject *
Xxo_demo(XxoObject * self,PyObject * args)57 Xxo_demo(XxoObject *self, PyObject *args)
58 {
59 PyObject *o = NULL;
60 if (!PyArg_ParseTuple(args, "|O:demo", &o))
61 return NULL;
62 /* Test availability of fast type checks */
63 if (o != NULL && PyUnicode_Check(o)) {
64 Py_INCREF(o);
65 return o;
66 }
67 Py_INCREF(Py_None);
68 return Py_None;
69 }
70
71 static PyMethodDef Xxo_methods[] = {
72 {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
73 PyDoc_STR("demo() -> None")},
74 {NULL, NULL} /* sentinel */
75 };
76
77 static PyObject *
Xxo_getattro(XxoObject * self,PyObject * name)78 Xxo_getattro(XxoObject *self, PyObject *name)
79 {
80 if (self->x_attr != NULL) {
81 PyObject *v = PyDict_GetItemWithError(self->x_attr, name);
82 if (v != NULL) {
83 Py_INCREF(v);
84 return v;
85 }
86 else if (PyErr_Occurred()) {
87 return NULL;
88 }
89 }
90 return PyObject_GenericGetAttr((PyObject *)self, name);
91 }
92
93 static int
Xxo_setattr(XxoObject * self,const char * name,PyObject * v)94 Xxo_setattr(XxoObject *self, const char *name, PyObject *v)
95 {
96 if (self->x_attr == NULL) {
97 self->x_attr = PyDict_New();
98 if (self->x_attr == NULL)
99 return -1;
100 }
101 if (v == NULL) {
102 int rv = PyDict_DelItemString(self->x_attr, name);
103 if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
104 PyErr_SetString(PyExc_AttributeError,
105 "delete non-existing Xxo attribute");
106 return rv;
107 }
108 else
109 return PyDict_SetItemString(self->x_attr, name, v);
110 }
111
112 static PyType_Slot Xxo_Type_slots[] = {
113 {Py_tp_doc, "The Xxo type"},
114 {Py_tp_traverse, Xxo_traverse},
115 {Py_tp_finalize, Xxo_finalize},
116 {Py_tp_getattro, Xxo_getattro},
117 {Py_tp_setattr, Xxo_setattr},
118 {Py_tp_methods, Xxo_methods},
119 {0, 0},
120 };
121
122 static PyType_Spec Xxo_Type_spec = {
123 "xxlimited.Xxo",
124 sizeof(XxoObject),
125 0,
126 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
127 Xxo_Type_slots
128 };
129
130 /* --------------------------------------------------------------------- */
131
132 /* Function of two integers returning integer */
133
134 PyDoc_STRVAR(xx_foo_doc,
135 "foo(i,j)\n\
136 \n\
137 Return the sum of i and j.");
138
139 static PyObject *
xx_foo(PyObject * self,PyObject * args)140 xx_foo(PyObject *self, PyObject *args)
141 {
142 long i, j;
143 long res;
144 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
145 return NULL;
146 res = i+j; /* XXX Do something here */
147 return PyLong_FromLong(res);
148 }
149
150
151 /* Function of no arguments returning new Xxo object */
152
153 static PyObject *
xx_new(PyObject * self,PyObject * args)154 xx_new(PyObject *self, PyObject *args)
155 {
156 XxoObject *rv;
157
158 if (!PyArg_ParseTuple(args, ":new"))
159 return NULL;
160 rv = newXxoObject(args);
161 if (rv == NULL)
162 return NULL;
163 return (PyObject *)rv;
164 }
165
166 /* Test bad format character */
167
168 static PyObject *
xx_roj(PyObject * self,PyObject * args)169 xx_roj(PyObject *self, PyObject *args)
170 {
171 PyObject *a;
172 long b;
173 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
174 return NULL;
175 Py_INCREF(Py_None);
176 return Py_None;
177 }
178
179
180 /* ---------- */
181
182 static PyType_Slot Str_Type_slots[] = {
183 {Py_tp_base, NULL}, /* filled out in module init function */
184 {0, 0},
185 };
186
187 static PyType_Spec Str_Type_spec = {
188 "xxlimited.Str",
189 0,
190 0,
191 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
192 Str_Type_slots
193 };
194
195 /* ---------- */
196
197 static PyObject *
null_richcompare(PyObject * self,PyObject * other,int op)198 null_richcompare(PyObject *self, PyObject *other, int op)
199 {
200 Py_RETURN_NOTIMPLEMENTED;
201 }
202
203 static PyType_Slot Null_Type_slots[] = {
204 {Py_tp_base, NULL}, /* filled out in module init */
205 {Py_tp_new, NULL},
206 {Py_tp_richcompare, null_richcompare},
207 {0, 0}
208 };
209
210 static PyType_Spec Null_Type_spec = {
211 "xxlimited.Null",
212 0, /* basicsize */
213 0, /* itemsize */
214 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
215 Null_Type_slots
216 };
217
218 /* ---------- */
219
220 /* List of functions defined in the module */
221
222 static PyMethodDef xx_methods[] = {
223 {"roj", xx_roj, METH_VARARGS,
224 PyDoc_STR("roj(a,b) -> None")},
225 {"foo", xx_foo, METH_VARARGS,
226 xx_foo_doc},
227 {"new", xx_new, METH_VARARGS,
228 PyDoc_STR("new() -> new Xx object")},
229 {NULL, NULL} /* sentinel */
230 };
231
232 PyDoc_STRVAR(module_doc,
233 "This is a template module just for instruction.");
234
235 static int
xx_modexec(PyObject * m)236 xx_modexec(PyObject *m)
237 {
238 PyObject *o;
239
240 /* Due to cross platform compiler issues the slots must be filled
241 * here. It's required for portability to Windows without requiring
242 * C++. */
243 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
244 Null_Type_slots[1].pfunc = PyType_GenericNew;
245 Str_Type_slots[0].pfunc = &PyUnicode_Type;
246
247 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
248 if (Xxo_Type == NULL)
249 goto fail;
250
251 /* Add some symbolic constants to the module */
252 if (ErrorObject == NULL) {
253 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
254 if (ErrorObject == NULL)
255 goto fail;
256 }
257 Py_INCREF(ErrorObject);
258 PyModule_AddObject(m, "error", ErrorObject);
259
260 /* Add Xxo */
261 o = PyType_FromSpec(&Xxo_Type_spec);
262 if (o == NULL)
263 goto fail;
264 PyModule_AddObject(m, "Xxo", o);
265
266 /* Add Str */
267 o = PyType_FromSpec(&Str_Type_spec);
268 if (o == NULL)
269 goto fail;
270 PyModule_AddObject(m, "Str", o);
271
272 /* Add Null */
273 o = PyType_FromSpec(&Null_Type_spec);
274 if (o == NULL)
275 goto fail;
276 PyModule_AddObject(m, "Null", o);
277 return 0;
278 fail:
279 Py_XDECREF(m);
280 return -1;
281 }
282
283
284 static PyModuleDef_Slot xx_slots[] = {
285 {Py_mod_exec, xx_modexec},
286 {0, NULL}
287 };
288
289 static struct PyModuleDef xxmodule = {
290 PyModuleDef_HEAD_INIT,
291 "xxlimited",
292 module_doc,
293 0,
294 xx_methods,
295 xx_slots,
296 NULL,
297 NULL,
298 NULL
299 };
300
301 /* Export function for the module (*must* be called PyInit_xx) */
302
303 PyMODINIT_FUNC
PyInit_xxlimited(void)304 PyInit_xxlimited(void)
305 {
306 return PyModuleDef_Init(&xxmodule);
307 }
308