blob: bd3f1783e6797d4825973b0894c9887bec1aeb8d [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);
47 PyObject_Del(self);
48}
49
50static PyObject *
51Xxo_demo(XxoObject *self, PyObject *args)
52{
53 if (!PyArg_ParseTuple(args, ":demo"))
54 return NULL;
55 Py_INCREF(Py_None);
56 return Py_None;
57}
58
59static PyMethodDef Xxo_methods[] = {
60 {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
61 PyDoc_STR("demo() -> None")},
62 {NULL, NULL} /* sentinel */
63};
64
65static PyObject *
66Xxo_getattro(XxoObject *self, PyObject *name)
67{
68 if (self->x_attr != NULL) {
69 PyObject *v = PyDict_GetItem(self->x_attr, name);
70 if (v != NULL) {
71 Py_INCREF(v);
72 return v;
73 }
74 }
75 return PyObject_GenericGetAttr((PyObject *)self, name);
76}
77
78static int
79Xxo_setattr(XxoObject *self, char *name, PyObject *v)
80{
81 if (self->x_attr == NULL) {
82 self->x_attr = PyDict_New();
83 if (self->x_attr == NULL)
84 return -1;
85 }
86 if (v == NULL) {
87 int rv = PyDict_DelItemString(self->x_attr, name);
88 if (rv < 0)
89 PyErr_SetString(PyExc_AttributeError,
90 "delete non-existing Xxo attribute");
91 return rv;
92 }
93 else
94 return PyDict_SetItemString(self->x_attr, name, v);
95}
96
97static PyType_Slot Xxo_Type_slots[] = {
98 {Py_tp_dealloc, Xxo_dealloc},
99 {Py_tp_getattro, Xxo_getattro},
100 {Py_tp_setattr, Xxo_setattr},
101 {Py_tp_methods, Xxo_methods},
102 {0, 0},
103};
104
105static PyType_Spec Xxo_Type_spec = {
106 "xxmodule.Xxo",
107 NULL,
108 sizeof(XxoObject),
109 0,
110 Py_TPFLAGS_DEFAULT,
111 Xxo_Type_slots
112};
113
114/* --------------------------------------------------------------------- */
115
116/* Function of two integers returning integer */
117
118PyDoc_STRVAR(xx_foo_doc,
119"foo(i,j)\n\
120\n\
121Return the sum of i and j.");
122
123static PyObject *
124xx_foo(PyObject *self, PyObject *args)
125{
126 long i, j;
127 long res;
128 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
129 return NULL;
130 res = i+j; /* XXX Do something here */
131 return PyLong_FromLong(res);
132}
133
134
135/* Function of no arguments returning new Xxo object */
136
137static PyObject *
138xx_new(PyObject *self, PyObject *args)
139{
140 XxoObject *rv;
141
142 if (!PyArg_ParseTuple(args, ":new"))
143 return NULL;
144 rv = newXxoObject(args);
145 if (rv == NULL)
146 return NULL;
147 return (PyObject *)rv;
148}
149
150/* Test bad format character */
151
152static PyObject *
153xx_roj(PyObject *self, PyObject *args)
154{
155 PyObject *a;
156 long b;
157 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
158 return NULL;
159 Py_INCREF(Py_None);
160 return Py_None;
161}
162
163
164/* ---------- */
165
166static PyType_Slot Str_Type_slots[] = {
167 {Py_tp_base, NULL}, /* filled out in module init function */
168 {0, 0},
169};
170
171static PyType_Spec Str_Type_spec = {
172 "xxlimited.Str",
173 0,
174 0,
175 0,
176 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
177 Str_Type_slots
178};
179
180/* ---------- */
181
182static PyObject *
183null_richcompare(PyObject *self, PyObject *other, int op)
184{
185 Py_INCREF(Py_NotImplemented);
186 return Py_NotImplemented;
187}
188
189static PyType_Slot Null_Type_slots[] = {
190 {Py_tp_base, NULL}, /* filled out in module init */
191 {Py_tp_new, NULL},
192 {Py_tp_richcompare, null_richcompare},
193 {0, 0}
194};
195
196static PyType_Spec Null_Type_spec = {
197 "xxlimited.Null",
198 NULL, /* doc */
199 0, /* basicsize */
200 0, /* itemsize */
201 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
202 Null_Type_slots
203};
204
205/* ---------- */
206
207/* List of functions defined in the module */
208
209static PyMethodDef xx_methods[] = {
210 {"roj", xx_roj, METH_VARARGS,
211 PyDoc_STR("roj(a,b) -> None")},
212 {"foo", xx_foo, METH_VARARGS,
213 xx_foo_doc},
214 {"new", xx_new, METH_VARARGS,
215 PyDoc_STR("new() -> new Xx object")},
216 {NULL, NULL} /* sentinel */
217};
218
219PyDoc_STRVAR(module_doc,
220"This is a template module just for instruction.");
221
222/* Initialization function for the module (*must* be called PyInit_xx) */
223
224
225static struct PyModuleDef xxmodule = {
226 PyModuleDef_HEAD_INIT,
227 "xx",
228 module_doc,
229 -1,
230 xx_methods,
231 NULL,
232 NULL,
233 NULL,
234 NULL
235};
236
237PyMODINIT_FUNC
238PyInit_xxlimited(void)
239{
240 PyObject *m = NULL;
241 PyObject *o;
242
243 /* Due to cross platform compiler issues the slots must be filled
244 * here. It's required for portability to Windows without requiring
245 * C++. */
246 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
247 Null_Type_slots[1].pfunc = PyType_GenericNew;
248 Str_Type_slots[0].pfunc = &PyUnicode_Type;
249
250 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
251 if (Xxo_Type == NULL)
252 goto fail;
253
254 /* Create the module and add the functions */
255 m = PyModule_Create(&xxmodule);
256 if (m == NULL)
257 goto fail;
258
259 /* Add some symbolic constants to the module */
260 if (ErrorObject == NULL) {
261 ErrorObject = PyErr_NewException("xx.error", NULL, NULL);
262 if (ErrorObject == NULL)
263 goto fail;
264 }
265 Py_INCREF(ErrorObject);
266 PyModule_AddObject(m, "error", ErrorObject);
267
268 /* Add Str */
269 o = PyType_FromSpec(&Str_Type_spec);
270 if (o == NULL)
271 goto fail;
272 PyModule_AddObject(m, "Str", o);
273
274 /* Add Null */
275 o = PyType_FromSpec(&Null_Type_spec);
276 if (o == NULL)
277 goto fail;
278 PyModule_AddObject(m, "Null", o);
279 return m;
280 fail:
281 Py_XDECREF(m);
282 return NULL;
283}