blob: 5b05a9454a05dac9817cef385f95169602b6eb90 [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
Dong-hee Na1b55b652020-02-17 19:09:15 +090028#define XxoObject_Check(v) Py_IS_TYPE(v, Xxo_Type)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000029
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{
Pablo Galindo1cf15af2020-05-27 10:03:38 +010046 Py_VISIT(Py_TYPE(self));
Nick Coghlan53f95022015-06-04 21:52:57 +100047 Py_VISIT(self->x_attr);
48 return 0;
49}
50
Serhiy Storchaka19de8b32018-05-26 10:51:58 +030051static void
Nick Coghlan53f95022015-06-04 21:52:57 +100052Xxo_finalize(XxoObject *self)
53{
54 Py_CLEAR(self->x_attr);
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) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +020082 PyObject *v = PyDict_GetItemWithError(self->x_attr, name);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000083 if (v != NULL) {
84 Py_INCREF(v);
85 return v;
86 }
Serhiy Storchakaa24107b2019-02-25 17:59:46 +020087 else if (PyErr_Occurred()) {
88 return NULL;
89 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000090 }
91 return PyObject_GenericGetAttr((PyObject *)self, name);
92}
93
94static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020095Xxo_setattr(XxoObject *self, const char *name, PyObject *v)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000096{
97 if (self->x_attr == NULL) {
98 self->x_attr = PyDict_New();
99 if (self->x_attr == NULL)
100 return -1;
101 }
102 if (v == NULL) {
103 int rv = PyDict_DelItemString(self->x_attr, name);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200104 if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000105 PyErr_SetString(PyExc_AttributeError,
106 "delete non-existing Xxo attribute");
107 return rv;
108 }
109 else
110 return PyDict_SetItemString(self->x_attr, name, v);
111}
112
113static PyType_Slot Xxo_Type_slots[] = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000114 {Py_tp_doc, "The Xxo type"},
Nick Coghlan53f95022015-06-04 21:52:57 +1000115 {Py_tp_traverse, Xxo_traverse},
116 {Py_tp_finalize, Xxo_finalize},
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000117 {Py_tp_getattro, Xxo_getattro},
118 {Py_tp_setattr, Xxo_setattr},
119 {Py_tp_methods, Xxo_methods},
120 {0, 0},
121};
122
123static PyType_Spec Xxo_Type_spec = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000124 "xxlimited.Xxo",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000125 sizeof(XxoObject),
126 0,
Antoine Pitrouada319b2019-05-29 22:12:38 +0200127 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000128 Xxo_Type_slots
129};
130
131/* --------------------------------------------------------------------- */
132
133/* Function of two integers returning integer */
134
135PyDoc_STRVAR(xx_foo_doc,
136"foo(i,j)\n\
137\n\
138Return the sum of i and j.");
139
140static PyObject *
141xx_foo(PyObject *self, PyObject *args)
142{
143 long i, j;
144 long res;
145 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
146 return NULL;
147 res = i+j; /* XXX Do something here */
148 return PyLong_FromLong(res);
149}
150
151
152/* Function of no arguments returning new Xxo object */
153
154static PyObject *
155xx_new(PyObject *self, PyObject *args)
156{
157 XxoObject *rv;
158
159 if (!PyArg_ParseTuple(args, ":new"))
160 return NULL;
161 rv = newXxoObject(args);
162 if (rv == NULL)
163 return NULL;
164 return (PyObject *)rv;
165}
166
167/* Test bad format character */
168
169static PyObject *
170xx_roj(PyObject *self, PyObject *args)
171{
172 PyObject *a;
173 long b;
174 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
175 return NULL;
176 Py_INCREF(Py_None);
177 return Py_None;
178}
179
180
181/* ---------- */
182
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200183static PyType_Slot Str_Type_slots[] = {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000184 {Py_tp_base, NULL}, /* filled out in module init function */
185 {0, 0},
186};
187
188static PyType_Spec Str_Type_spec = {
189 "xxlimited.Str",
190 0,
191 0,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000192 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
193 Str_Type_slots
194};
195
196/* ---------- */
197
198static PyObject *
199null_richcompare(PyObject *self, PyObject *other, int op)
200{
Brian Curtindfc80e32011-08-10 20:28:54 -0500201 Py_RETURN_NOTIMPLEMENTED;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000202}
203
204static PyType_Slot Null_Type_slots[] = {
205 {Py_tp_base, NULL}, /* filled out in module init */
206 {Py_tp_new, NULL},
207 {Py_tp_richcompare, null_richcompare},
208 {0, 0}
209};
210
211static PyType_Spec Null_Type_spec = {
212 "xxlimited.Null",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000213 0, /* basicsize */
214 0, /* itemsize */
215 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
216 Null_Type_slots
217};
218
219/* ---------- */
220
221/* List of functions defined in the module */
222
223static PyMethodDef xx_methods[] = {
224 {"roj", xx_roj, METH_VARARGS,
225 PyDoc_STR("roj(a,b) -> None")},
226 {"foo", xx_foo, METH_VARARGS,
227 xx_foo_doc},
228 {"new", xx_new, METH_VARARGS,
229 PyDoc_STR("new() -> new Xx object")},
230 {NULL, NULL} /* sentinel */
231};
232
233PyDoc_STRVAR(module_doc,
234"This is a template module just for instruction.");
235
Nick Coghland5cacbb2015-05-23 22:24:10 +1000236static int
237xx_modexec(PyObject *m)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000238{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000239 PyObject *o;
240
241 /* Due to cross platform compiler issues the slots must be filled
242 * here. It's required for portability to Windows without requiring
243 * C++. */
244 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
245 Null_Type_slots[1].pfunc = PyType_GenericNew;
246 Str_Type_slots[0].pfunc = &PyUnicode_Type;
247
248 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
249 if (Xxo_Type == NULL)
250 goto fail;
251
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000252 /* Add some symbolic constants to the module */
253 if (ErrorObject == NULL) {
Martin v. Löwis69168062011-02-11 20:47:49 +0000254 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000255 if (ErrorObject == NULL)
256 goto fail;
257 }
258 Py_INCREF(ErrorObject);
259 PyModule_AddObject(m, "error", ErrorObject);
260
Nick Coghlan53f95022015-06-04 21:52:57 +1000261 /* Add Xxo */
262 o = PyType_FromSpec(&Xxo_Type_spec);
263 if (o == NULL)
264 goto fail;
265 PyModule_AddObject(m, "Xxo", o);
266
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000267 /* Add Str */
268 o = PyType_FromSpec(&Str_Type_spec);
269 if (o == NULL)
270 goto fail;
271 PyModule_AddObject(m, "Str", o);
272
273 /* Add Null */
274 o = PyType_FromSpec(&Null_Type_spec);
275 if (o == NULL)
276 goto fail;
277 PyModule_AddObject(m, "Null", o);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000278 return 0;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000279 fail:
280 Py_XDECREF(m);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000281 return -1;
282}
283
284
285static PyModuleDef_Slot xx_slots[] = {
286 {Py_mod_exec, xx_modexec},
287 {0, NULL}
288};
289
290static struct PyModuleDef xxmodule = {
291 PyModuleDef_HEAD_INIT,
292 "xxlimited",
293 module_doc,
294 0,
295 xx_methods,
296 xx_slots,
297 NULL,
298 NULL,
299 NULL
300};
301
302/* Export function for the module (*must* be called PyInit_xx) */
303
304PyMODINIT_FUNC
305PyInit_xxlimited(void)
306{
307 return PyModuleDef_Init(&xxmodule);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000308}