blob: 40c176063dbac4ea393ab2ba66b5aeb6eec20f47 [file] [log] [blame]
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001
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
19static PyObject *ErrorObject;
20
21typedef struct {
22 PyObject_HEAD
23 PyObject *x_attr; /* Attributes dictionary */
24} XxoObject;
25
26static PyObject *Xxo_Type;
27
28#define XxoObject_Check(v) (Py_TYPE(v) == Xxo_Type)
29
30static XxoObject *
31newXxoObject(PyObject *arg)
32{
33 XxoObject *self;
34 self = PyObject_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
Nick Coghlan53f95022015-06-04 21:52:57 +100043static int
44Xxo_traverse(XxoObject *self, visitproc visit, void *arg)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000045{
Nick Coghlan53f95022015-06-04 21:52:57 +100046 Py_VISIT(self->x_attr);
47 return 0;
48}
49
50static int
51Xxo_finalize(XxoObject *self)
52{
53 Py_CLEAR(self->x_attr);
54 return 0;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000055}
56
57static PyObject *
58Xxo_demo(XxoObject *self, PyObject *args)
59{
Martin v. Löwis738236d2011-02-05 20:35:29 +000060 PyObject *o = NULL;
61 if (!PyArg_ParseTuple(args, "|O:demo", &o))
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000062 return NULL;
Martin v. Löwis738236d2011-02-05 20:35:29 +000063 /* Test availability of fast type checks */
64 if (o != NULL && PyUnicode_Check(o)) {
65 Py_INCREF(o);
66 return o;
67 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000068 Py_INCREF(Py_None);
69 return Py_None;
70}
71
72static PyMethodDef Xxo_methods[] = {
73 {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
74 PyDoc_STR("demo() -> None")},
75 {NULL, NULL} /* sentinel */
76};
77
78static PyObject *
79Xxo_getattro(XxoObject *self, PyObject *name)
80{
81 if (self->x_attr != NULL) {
82 PyObject *v = PyDict_GetItem(self->x_attr, name);
83 if (v != NULL) {
84 Py_INCREF(v);
85 return v;
86 }
87 }
88 return PyObject_GenericGetAttr((PyObject *)self, name);
89}
90
91static int
92Xxo_setattr(XxoObject *self, char *name, PyObject *v)
93{
94 if (self->x_attr == NULL) {
95 self->x_attr = PyDict_New();
96 if (self->x_attr == NULL)
97 return -1;
98 }
99 if (v == NULL) {
100 int rv = PyDict_DelItemString(self->x_attr, name);
101 if (rv < 0)
102 PyErr_SetString(PyExc_AttributeError,
103 "delete non-existing Xxo attribute");
104 return rv;
105 }
106 else
107 return PyDict_SetItemString(self->x_attr, name, v);
108}
109
110static PyType_Slot Xxo_Type_slots[] = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000111 {Py_tp_doc, "The Xxo type"},
Nick Coghlan53f95022015-06-04 21:52:57 +1000112 {Py_tp_traverse, Xxo_traverse},
113 {Py_tp_finalize, Xxo_finalize},
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000114 {Py_tp_getattro, Xxo_getattro},
115 {Py_tp_setattr, Xxo_setattr},
116 {Py_tp_methods, Xxo_methods},
117 {0, 0},
118};
119
120static PyType_Spec Xxo_Type_spec = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000121 "xxlimited.Xxo",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000122 sizeof(XxoObject),
123 0,
Nick Coghlan53f95022015-06-04 21:52:57 +1000124 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000125 Xxo_Type_slots
126};
127
128/* --------------------------------------------------------------------- */
129
130/* Function of two integers returning integer */
131
132PyDoc_STRVAR(xx_foo_doc,
133"foo(i,j)\n\
134\n\
135Return the sum of i and j.");
136
137static PyObject *
138xx_foo(PyObject *self, PyObject *args)
139{
140 long i, j;
141 long res;
142 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
143 return NULL;
144 res = i+j; /* XXX Do something here */
145 return PyLong_FromLong(res);
146}
147
148
149/* Function of no arguments returning new Xxo object */
150
151static PyObject *
152xx_new(PyObject *self, PyObject *args)
153{
154 XxoObject *rv;
155
156 if (!PyArg_ParseTuple(args, ":new"))
157 return NULL;
158 rv = newXxoObject(args);
159 if (rv == NULL)
160 return NULL;
161 return (PyObject *)rv;
162}
163
164/* Test bad format character */
165
166static PyObject *
167xx_roj(PyObject *self, PyObject *args)
168{
169 PyObject *a;
170 long b;
171 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
172 return NULL;
173 Py_INCREF(Py_None);
174 return Py_None;
175}
176
177
178/* ---------- */
179
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200180static PyType_Slot Str_Type_slots[] = {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000181 {Py_tp_base, NULL}, /* filled out in module init function */
182 {0, 0},
183};
184
185static PyType_Spec Str_Type_spec = {
186 "xxlimited.Str",
187 0,
188 0,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000189 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
190 Str_Type_slots
191};
192
193/* ---------- */
194
195static PyObject *
196null_richcompare(PyObject *self, PyObject *other, int op)
197{
Brian Curtindfc80e32011-08-10 20:28:54 -0500198 Py_RETURN_NOTIMPLEMENTED;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000199}
200
201static PyType_Slot Null_Type_slots[] = {
202 {Py_tp_base, NULL}, /* filled out in module init */
203 {Py_tp_new, NULL},
204 {Py_tp_richcompare, null_richcompare},
205 {0, 0}
206};
207
208static PyType_Spec Null_Type_spec = {
209 "xxlimited.Null",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000210 0, /* basicsize */
211 0, /* itemsize */
212 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
213 Null_Type_slots
214};
215
216/* ---------- */
217
218/* List of functions defined in the module */
219
220static PyMethodDef xx_methods[] = {
221 {"roj", xx_roj, METH_VARARGS,
222 PyDoc_STR("roj(a,b) -> None")},
223 {"foo", xx_foo, METH_VARARGS,
224 xx_foo_doc},
225 {"new", xx_new, METH_VARARGS,
226 PyDoc_STR("new() -> new Xx object")},
227 {NULL, NULL} /* sentinel */
228};
229
230PyDoc_STRVAR(module_doc,
231"This is a template module just for instruction.");
232
Nick Coghland5cacbb2015-05-23 22:24:10 +1000233static int
234xx_modexec(PyObject *m)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000235{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000236 PyObject *o;
237
238 /* Due to cross platform compiler issues the slots must be filled
239 * here. It's required for portability to Windows without requiring
240 * C++. */
241 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
242 Null_Type_slots[1].pfunc = PyType_GenericNew;
243 Str_Type_slots[0].pfunc = &PyUnicode_Type;
244
245 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
246 if (Xxo_Type == NULL)
247 goto fail;
248
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000249 /* Add some symbolic constants to the module */
250 if (ErrorObject == NULL) {
Martin v. Löwis69168062011-02-11 20:47:49 +0000251 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000252 if (ErrorObject == NULL)
253 goto fail;
254 }
255 Py_INCREF(ErrorObject);
256 PyModule_AddObject(m, "error", ErrorObject);
257
Nick Coghlan53f95022015-06-04 21:52:57 +1000258 /* Add Xxo */
259 o = PyType_FromSpec(&Xxo_Type_spec);
260 if (o == NULL)
261 goto fail;
262 PyModule_AddObject(m, "Xxo", o);
263
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000264 /* Add Str */
265 o = PyType_FromSpec(&Str_Type_spec);
266 if (o == NULL)
267 goto fail;
268 PyModule_AddObject(m, "Str", o);
269
270 /* Add Null */
271 o = PyType_FromSpec(&Null_Type_spec);
272 if (o == NULL)
273 goto fail;
274 PyModule_AddObject(m, "Null", o);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000275 return 0;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000276 fail:
277 Py_XDECREF(m);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000278 return -1;
279}
280
281
282static PyModuleDef_Slot xx_slots[] = {
283 {Py_mod_exec, xx_modexec},
284 {0, NULL}
285};
286
287static struct PyModuleDef xxmodule = {
288 PyModuleDef_HEAD_INIT,
289 "xxlimited",
290 module_doc,
291 0,
292 xx_methods,
293 xx_slots,
294 NULL,
295 NULL,
296 NULL
297};
298
299/* Export function for the module (*must* be called PyInit_xx) */
300
301PyMODINIT_FUNC
302PyInit_xxlimited(void)
303{
304 return PyModuleDef_Init(&xxmodule);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000305}