blob: ffc04e0310e392780625b13d62a850aaa66078e5 [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) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +020081 PyObject *v = PyDict_GetItemWithError(self->x_attr, name);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000082 if (v != NULL) {
83 Py_INCREF(v);
84 return v;
85 }
Serhiy Storchakaa24107b2019-02-25 17:59:46 +020086 else if (PyErr_Occurred()) {
87 return NULL;
88 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000089 }
90 return PyObject_GenericGetAttr((PyObject *)self, name);
91}
92
93static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020094Xxo_setattr(XxoObject *self, const char *name, PyObject *v)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000095{
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);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200103 if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000104 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
112static PyType_Slot Xxo_Type_slots[] = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000113 {Py_tp_doc, "The Xxo type"},
Nick Coghlan53f95022015-06-04 21:52:57 +1000114 {Py_tp_traverse, Xxo_traverse},
115 {Py_tp_finalize, Xxo_finalize},
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000116 {Py_tp_getattro, Xxo_getattro},
117 {Py_tp_setattr, Xxo_setattr},
118 {Py_tp_methods, Xxo_methods},
119 {0, 0},
120};
121
122static PyType_Spec Xxo_Type_spec = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000123 "xxlimited.Xxo",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000124 sizeof(XxoObject),
125 0,
Antoine Pitrouada319b2019-05-29 22:12:38 +0200126 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000127 Xxo_Type_slots
128};
129
130/* --------------------------------------------------------------------- */
131
132/* Function of two integers returning integer */
133
134PyDoc_STRVAR(xx_foo_doc,
135"foo(i,j)\n\
136\n\
137Return the sum of i and j.");
138
139static PyObject *
140xx_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
153static PyObject *
154xx_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
168static PyObject *
169xx_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
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200182static PyType_Slot Str_Type_slots[] = {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000183 {Py_tp_base, NULL}, /* filled out in module init function */
184 {0, 0},
185};
186
187static PyType_Spec Str_Type_spec = {
188 "xxlimited.Str",
189 0,
190 0,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000191 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
192 Str_Type_slots
193};
194
195/* ---------- */
196
197static PyObject *
198null_richcompare(PyObject *self, PyObject *other, int op)
199{
Brian Curtindfc80e32011-08-10 20:28:54 -0500200 Py_RETURN_NOTIMPLEMENTED;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000201}
202
203static 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
210static PyType_Spec Null_Type_spec = {
211 "xxlimited.Null",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000212 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
222static 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
232PyDoc_STRVAR(module_doc,
233"This is a template module just for instruction.");
234
Nick Coghland5cacbb2015-05-23 22:24:10 +1000235static int
236xx_modexec(PyObject *m)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000237{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000238 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
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000251 /* Add some symbolic constants to the module */
252 if (ErrorObject == NULL) {
Martin v. Löwis69168062011-02-11 20:47:49 +0000253 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000254 if (ErrorObject == NULL)
255 goto fail;
256 }
257 Py_INCREF(ErrorObject);
258 PyModule_AddObject(m, "error", ErrorObject);
259
Nick Coghlan53f95022015-06-04 21:52:57 +1000260 /* Add Xxo */
261 o = PyType_FromSpec(&Xxo_Type_spec);
262 if (o == NULL)
263 goto fail;
264 PyModule_AddObject(m, "Xxo", o);
265
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000266 /* 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);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000277 return 0;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000278 fail:
279 Py_XDECREF(m);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000280 return -1;
281}
282
283
284static PyModuleDef_Slot xx_slots[] = {
285 {Py_mod_exec, xx_modexec},
286 {0, NULL}
287};
288
289static 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
303PyMODINIT_FUNC
304PyInit_xxlimited(void)
305{
306 return PyModuleDef_Init(&xxmodule);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000307}