blob: 5586989d039cfe1ac3e7b8fee2086bc3f32dd0f9 [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;
Benjamin Petersonec977c32017-01-31 23:31:02 -080034 self = PyObject_GC_New(XxoObject, (PyTypeObject*)Xxo_Type);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000035 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
Serhiy Storchaka19de8b32018-05-26 10:51:58 +030050static void
Nick Coghlan53f95022015-06-04 21:52:57 +100051Xxo_finalize(XxoObject *self)
52{
53 Py_CLEAR(self->x_attr);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000054}
55
56static PyObject *
57Xxo_demo(XxoObject *self, PyObject *args)
58{
Martin v. Löwis738236d2011-02-05 20:35:29 +000059 PyObject *o = NULL;
60 if (!PyArg_ParseTuple(args, "|O:demo", &o))
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000061 return NULL;
Martin v. Löwis738236d2011-02-05 20:35:29 +000062 /* Test availability of fast type checks */
63 if (o != NULL && PyUnicode_Check(o)) {
64 Py_INCREF(o);
65 return o;
66 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000067 Py_INCREF(Py_None);
68 return Py_None;
69}
70
71static PyMethodDef Xxo_methods[] = {
72 {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
73 PyDoc_STR("demo() -> None")},
74 {NULL, NULL} /* sentinel */
75};
76
77static PyObject *
78Xxo_getattro(XxoObject *self, PyObject *name)
79{
80 if (self->x_attr != NULL) {
81 PyObject *v = PyDict_GetItem(self->x_attr, name);
82 if (v != NULL) {
83 Py_INCREF(v);
84 return v;
85 }
86 }
87 return PyObject_GenericGetAttr((PyObject *)self, name);
88}
89
90static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020091Xxo_setattr(XxoObject *self, const char *name, PyObject *v)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000092{
93 if (self->x_attr == NULL) {
94 self->x_attr = PyDict_New();
95 if (self->x_attr == NULL)
96 return -1;
97 }
98 if (v == NULL) {
99 int rv = PyDict_DelItemString(self->x_attr, name);
100 if (rv < 0)
101 PyErr_SetString(PyExc_AttributeError,
102 "delete non-existing Xxo attribute");
103 return rv;
104 }
105 else
106 return PyDict_SetItemString(self->x_attr, name, v);
107}
108
109static PyType_Slot Xxo_Type_slots[] = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000110 {Py_tp_doc, "The Xxo type"},
Nick Coghlan53f95022015-06-04 21:52:57 +1000111 {Py_tp_traverse, Xxo_traverse},
112 {Py_tp_finalize, Xxo_finalize},
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000113 {Py_tp_getattro, Xxo_getattro},
114 {Py_tp_setattr, Xxo_setattr},
115 {Py_tp_methods, Xxo_methods},
116 {0, 0},
117};
118
119static PyType_Spec Xxo_Type_spec = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000120 "xxlimited.Xxo",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000121 sizeof(XxoObject),
122 0,
Nick Coghlan53f95022015-06-04 21:52:57 +1000123 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000124 Xxo_Type_slots
125};
126
127/* --------------------------------------------------------------------- */
128
129/* Function of two integers returning integer */
130
131PyDoc_STRVAR(xx_foo_doc,
132"foo(i,j)\n\
133\n\
134Return the sum of i and j.");
135
136static PyObject *
137xx_foo(PyObject *self, PyObject *args)
138{
139 long i, j;
140 long res;
141 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
142 return NULL;
143 res = i+j; /* XXX Do something here */
144 return PyLong_FromLong(res);
145}
146
147
148/* Function of no arguments returning new Xxo object */
149
150static PyObject *
151xx_new(PyObject *self, PyObject *args)
152{
153 XxoObject *rv;
154
155 if (!PyArg_ParseTuple(args, ":new"))
156 return NULL;
157 rv = newXxoObject(args);
158 if (rv == NULL)
159 return NULL;
160 return (PyObject *)rv;
161}
162
163/* Test bad format character */
164
165static PyObject *
166xx_roj(PyObject *self, PyObject *args)
167{
168 PyObject *a;
169 long b;
170 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
171 return NULL;
172 Py_INCREF(Py_None);
173 return Py_None;
174}
175
176
177/* ---------- */
178
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200179static PyType_Slot Str_Type_slots[] = {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000180 {Py_tp_base, NULL}, /* filled out in module init function */
181 {0, 0},
182};
183
184static PyType_Spec Str_Type_spec = {
185 "xxlimited.Str",
186 0,
187 0,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000188 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
189 Str_Type_slots
190};
191
192/* ---------- */
193
194static PyObject *
195null_richcompare(PyObject *self, PyObject *other, int op)
196{
Brian Curtindfc80e32011-08-10 20:28:54 -0500197 Py_RETURN_NOTIMPLEMENTED;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000198}
199
200static PyType_Slot Null_Type_slots[] = {
201 {Py_tp_base, NULL}, /* filled out in module init */
202 {Py_tp_new, NULL},
203 {Py_tp_richcompare, null_richcompare},
204 {0, 0}
205};
206
207static PyType_Spec Null_Type_spec = {
208 "xxlimited.Null",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000209 0, /* basicsize */
210 0, /* itemsize */
211 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
212 Null_Type_slots
213};
214
215/* ---------- */
216
217/* List of functions defined in the module */
218
219static PyMethodDef xx_methods[] = {
220 {"roj", xx_roj, METH_VARARGS,
221 PyDoc_STR("roj(a,b) -> None")},
222 {"foo", xx_foo, METH_VARARGS,
223 xx_foo_doc},
224 {"new", xx_new, METH_VARARGS,
225 PyDoc_STR("new() -> new Xx object")},
226 {NULL, NULL} /* sentinel */
227};
228
229PyDoc_STRVAR(module_doc,
230"This is a template module just for instruction.");
231
Nick Coghland5cacbb2015-05-23 22:24:10 +1000232static int
233xx_modexec(PyObject *m)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000234{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000235 PyObject *o;
236
237 /* Due to cross platform compiler issues the slots must be filled
238 * here. It's required for portability to Windows without requiring
239 * C++. */
240 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
241 Null_Type_slots[1].pfunc = PyType_GenericNew;
242 Str_Type_slots[0].pfunc = &PyUnicode_Type;
243
244 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
245 if (Xxo_Type == NULL)
246 goto fail;
247
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000248 /* Add some symbolic constants to the module */
249 if (ErrorObject == NULL) {
Martin v. Löwis69168062011-02-11 20:47:49 +0000250 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000251 if (ErrorObject == NULL)
252 goto fail;
253 }
254 Py_INCREF(ErrorObject);
255 PyModule_AddObject(m, "error", ErrorObject);
256
Nick Coghlan53f95022015-06-04 21:52:57 +1000257 /* Add Xxo */
258 o = PyType_FromSpec(&Xxo_Type_spec);
259 if (o == NULL)
260 goto fail;
261 PyModule_AddObject(m, "Xxo", o);
262
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000263 /* Add Str */
264 o = PyType_FromSpec(&Str_Type_spec);
265 if (o == NULL)
266 goto fail;
267 PyModule_AddObject(m, "Str", o);
268
269 /* Add Null */
270 o = PyType_FromSpec(&Null_Type_spec);
271 if (o == NULL)
272 goto fail;
273 PyModule_AddObject(m, "Null", o);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000274 return 0;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000275 fail:
276 Py_XDECREF(m);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000277 return -1;
278}
279
280
281static PyModuleDef_Slot xx_slots[] = {
282 {Py_mod_exec, xx_modexec},
283 {0, NULL}
284};
285
286static struct PyModuleDef xxmodule = {
287 PyModuleDef_HEAD_INIT,
288 "xxlimited",
289 module_doc,
290 0,
291 xx_methods,
292 xx_slots,
293 NULL,
294 NULL,
295 NULL
296};
297
298/* Export function for the module (*must* be called PyInit_xx) */
299
300PyMODINIT_FUNC
301PyInit_xxlimited(void)
302{
303 return PyModuleDef_Init(&xxmodule);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000304}