blob: ec924f2117bd78a73f21980969579a5b854b87fa [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{
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
172static PyType_Slot Str_Type_slots[] = {
173 {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{
190 Py_INCREF(Py_NotImplemented);
191 return Py_NotImplemented;
192}
193
194static PyType_Slot Null_Type_slots[] = {
195 {Py_tp_base, NULL}, /* filled out in module init */
196 {Py_tp_new, NULL},
197 {Py_tp_richcompare, null_richcompare},
198 {0, 0}
199};
200
201static PyType_Spec Null_Type_spec = {
202 "xxlimited.Null",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000203 0, /* basicsize */
204 0, /* itemsize */
205 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
206 Null_Type_slots
207};
208
209/* ---------- */
210
211/* List of functions defined in the module */
212
213static PyMethodDef xx_methods[] = {
214 {"roj", xx_roj, METH_VARARGS,
215 PyDoc_STR("roj(a,b) -> None")},
216 {"foo", xx_foo, METH_VARARGS,
217 xx_foo_doc},
218 {"new", xx_new, METH_VARARGS,
219 PyDoc_STR("new() -> new Xx object")},
220 {NULL, NULL} /* sentinel */
221};
222
223PyDoc_STRVAR(module_doc,
224"This is a template module just for instruction.");
225
226/* Initialization function for the module (*must* be called PyInit_xx) */
227
228
229static struct PyModuleDef xxmodule = {
230 PyModuleDef_HEAD_INIT,
Martin v. Löwis69168062011-02-11 20:47:49 +0000231 "xxlimited",
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000232 module_doc,
233 -1,
234 xx_methods,
235 NULL,
236 NULL,
237 NULL,
238 NULL
239};
240
241PyMODINIT_FUNC
242PyInit_xxlimited(void)
243{
244 PyObject *m = NULL;
245 PyObject *o;
246
247 /* Due to cross platform compiler issues the slots must be filled
248 * here. It's required for portability to Windows without requiring
249 * C++. */
250 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
251 Null_Type_slots[1].pfunc = PyType_GenericNew;
252 Str_Type_slots[0].pfunc = &PyUnicode_Type;
253
254 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
255 if (Xxo_Type == NULL)
256 goto fail;
257
258 /* Create the module and add the functions */
259 m = PyModule_Create(&xxmodule);
260 if (m == NULL)
261 goto fail;
262
263 /* Add some symbolic constants to the module */
264 if (ErrorObject == NULL) {
Martin v. Löwis69168062011-02-11 20:47:49 +0000265 ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL);
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000266 if (ErrorObject == NULL)
267 goto fail;
268 }
269 Py_INCREF(ErrorObject);
270 PyModule_AddObject(m, "error", ErrorObject);
271
272 /* Add Str */
273 o = PyType_FromSpec(&Str_Type_spec);
274 if (o == NULL)
275 goto fail;
276 PyModule_AddObject(m, "Str", o);
277
278 /* Add Null */
279 o = PyType_FromSpec(&Null_Type_spec);
280 if (o == NULL)
281 goto fail;
282 PyModule_AddObject(m, "Null", o);
283 return m;
284 fail:
285 Py_XDECREF(m);
286 return NULL;
287}