blob: 604456bffe674c560b71493a83e611a1a2fb033f [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
43static void
44Xxo_dealloc(XxoObject *self)
45{
46 Py_XDECREF(self->x_attr);
Martin v. Löwisca7b0462014-02-04 09:33:05 +010047 ((freefunc)PyType_GetSlot(Py_TYPE(self), Py_tp_free))(self);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000048}
49
50static PyObject *
51Xxo_demo(XxoObject *self, PyObject *args)
52{
Martin v. Löwis738236d2011-02-05 20:35:29 +000053 PyObject *o = NULL;
54 if (!PyArg_ParseTuple(args, "|O:demo", &o))
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000055 return NULL;
Martin v. Löwis738236d2011-02-05 20:35:29 +000056 /* Test availability of fast type checks */
57 if (o != NULL && PyUnicode_Check(o)) {
58 Py_INCREF(o);
59 return o;
60 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000061 Py_INCREF(Py_None);
62 return Py_None;
63}
64
65static PyMethodDef Xxo_methods[] = {
66 {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
67 PyDoc_STR("demo() -> None")},
68 {NULL, NULL} /* sentinel */
69};
70
71static PyObject *
72Xxo_getattro(XxoObject *self, PyObject *name)
73{
74 if (self->x_attr != NULL) {
75 PyObject *v = PyDict_GetItem(self->x_attr, name);
76 if (v != NULL) {
77 Py_INCREF(v);
78 return v;
79 }
80 }
81 return PyObject_GenericGetAttr((PyObject *)self, name);
82}
83
84static int
85Xxo_setattr(XxoObject *self, char *name, PyObject *v)
86{
87 if (self->x_attr == NULL) {
88 self->x_attr = PyDict_New();
89 if (self->x_attr == NULL)
90 return -1;
91 }
92 if (v == NULL) {
93 int rv = PyDict_DelItemString(self->x_attr, name);
94 if (rv < 0)
95 PyErr_SetString(PyExc_AttributeError,
96 "delete non-existing Xxo attribute");
97 return rv;
98 }
99 else
100 return PyDict_SetItemString(self->x_attr, name, v);
101}
102
103static PyType_Slot Xxo_Type_slots[] = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000104 {Py_tp_doc, "The Xxo type"},
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000105 {Py_tp_dealloc, Xxo_dealloc},
106 {Py_tp_getattro, Xxo_getattro},
107 {Py_tp_setattr, Xxo_setattr},
108 {Py_tp_methods, Xxo_methods},
109 {0, 0},
110};
111
112static PyType_Spec Xxo_Type_spec = {
Martin v. Löwis69168062011-02-11 20:47:49 +0000113 "xxlimited.Xxo",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000114 sizeof(XxoObject),
115 0,
116 Py_TPFLAGS_DEFAULT,
117 Xxo_Type_slots
118};
119
120/* --------------------------------------------------------------------- */
121
122/* Function of two integers returning integer */
123
124PyDoc_STRVAR(xx_foo_doc,
125"foo(i,j)\n\
126\n\
127Return the sum of i and j.");
128
129static PyObject *
130xx_foo(PyObject *self, PyObject *args)
131{
132 long i, j;
133 long res;
134 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
135 return NULL;
136 res = i+j; /* XXX Do something here */
137 return PyLong_FromLong(res);
138}
139
140
141/* Function of no arguments returning new Xxo object */
142
143static PyObject *
144xx_new(PyObject *self, PyObject *args)
145{
146 XxoObject *rv;
147
148 if (!PyArg_ParseTuple(args, ":new"))
149 return NULL;
150 rv = newXxoObject(args);
151 if (rv == NULL)
152 return NULL;
153 return (PyObject *)rv;
154}
155
156/* Test bad format character */
157
158static PyObject *
159xx_roj(PyObject *self, PyObject *args)
160{
161 PyObject *a;
162 long b;
163 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
164 return NULL;
165 Py_INCREF(Py_None);
166 return Py_None;
167}
168
169
170/* ---------- */
171
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200172static PyType_Slot Str_Type_slots[] = {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000173 {Py_tp_base, NULL}, /* filled out in module init function */
174 {0, 0},
175};
176
177static PyType_Spec Str_Type_spec = {
178 "xxlimited.Str",
179 0,
180 0,
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000181 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
182 Str_Type_slots
183};
184
185/* ---------- */
186
187static PyObject *
188null_richcompare(PyObject *self, PyObject *other, int op)
189{
Brian Curtindfc80e32011-08-10 20:28:54 -0500190 Py_RETURN_NOTIMPLEMENTED;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000191}
192
193static PyType_Slot Null_Type_slots[] = {
194 {Py_tp_base, NULL}, /* filled out in module init */
195 {Py_tp_new, NULL},
196 {Py_tp_richcompare, null_richcompare},
197 {0, 0}
198};
199
200static PyType_Spec Null_Type_spec = {
201 "xxlimited.Null",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000202 0, /* basicsize */
203 0, /* itemsize */
204 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
205 Null_Type_slots
206};
207
208/* ---------- */
209
210/* List of functions defined in the module */
211
212static PyMethodDef xx_methods[] = {
213 {"roj", xx_roj, METH_VARARGS,
214 PyDoc_STR("roj(a,b) -> None")},
215 {"foo", xx_foo, METH_VARARGS,
216 xx_foo_doc},
217 {"new", xx_new, METH_VARARGS,
218 PyDoc_STR("new() -> new Xx object")},
219 {NULL, NULL} /* sentinel */
220};
221
222PyDoc_STRVAR(module_doc,
223"This is a template module just for instruction.");
224
Nick Coghland5cacbb2015-05-23 22:24:10 +1000225static int
226xx_modexec(PyObject *m)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000227{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000228 PyObject *o;
229
230 /* Due to cross platform compiler issues the slots must be filled
231 * here. It's required for portability to Windows without requiring
232 * C++. */
233 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
234 Null_Type_slots[1].pfunc = PyType_GenericNew;
235 Str_Type_slots[0].pfunc = &PyUnicode_Type;
236
237 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
238 if (Xxo_Type == NULL)
239 goto fail;
240
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000241 /* Add some symbolic constants to the module */
242 if (ErrorObject == NULL) {
Martin v. Löwis69168062011-02-11 20:47:49 +0000243 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000244 if (ErrorObject == NULL)
245 goto fail;
246 }
247 Py_INCREF(ErrorObject);
248 PyModule_AddObject(m, "error", ErrorObject);
249
250 /* Add Str */
251 o = PyType_FromSpec(&Str_Type_spec);
252 if (o == NULL)
253 goto fail;
254 PyModule_AddObject(m, "Str", o);
255
256 /* Add Null */
257 o = PyType_FromSpec(&Null_Type_spec);
258 if (o == NULL)
259 goto fail;
260 PyModule_AddObject(m, "Null", o);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000261 return 0;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000262 fail:
263 Py_XDECREF(m);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000264 return -1;
265}
266
267
268static PyModuleDef_Slot xx_slots[] = {
269 {Py_mod_exec, xx_modexec},
270 {0, NULL}
271};
272
273static struct PyModuleDef xxmodule = {
274 PyModuleDef_HEAD_INIT,
275 "xxlimited",
276 module_doc,
277 0,
278 xx_methods,
279 xx_slots,
280 NULL,
281 NULL,
282 NULL
283};
284
285/* Export function for the module (*must* be called PyInit_xx) */
286
287PyMODINIT_FUNC
288PyInit_xxlimited(void)
289{
290 return PyModuleDef_Init(&xxmodule);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000291}