blob: 5a6df8f2d8fdb1a589bea98313510e8044916820 [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[] = {
104 {Py_tp_dealloc, Xxo_dealloc},
105 {Py_tp_getattro, Xxo_getattro},
106 {Py_tp_setattr, Xxo_setattr},
107 {Py_tp_methods, Xxo_methods},
108 {0, 0},
109};
110
111static PyType_Spec Xxo_Type_spec = {
112 "xxmodule.Xxo",
113 NULL,
114 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,
181 0,
182 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
183 Str_Type_slots
184};
185
186/* ---------- */
187
188static PyObject *
189null_richcompare(PyObject *self, PyObject *other, int op)
190{
191 Py_INCREF(Py_NotImplemented);
192 return Py_NotImplemented;
193}
194
195static PyType_Slot Null_Type_slots[] = {
196 {Py_tp_base, NULL}, /* filled out in module init */
197 {Py_tp_new, NULL},
198 {Py_tp_richcompare, null_richcompare},
199 {0, 0}
200};
201
202static PyType_Spec Null_Type_spec = {
203 "xxlimited.Null",
204 NULL, /* doc */
205 0, /* basicsize */
206 0, /* itemsize */
207 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
208 Null_Type_slots
209};
210
211/* ---------- */
212
213/* List of functions defined in the module */
214
215static PyMethodDef xx_methods[] = {
216 {"roj", xx_roj, METH_VARARGS,
217 PyDoc_STR("roj(a,b) -> None")},
218 {"foo", xx_foo, METH_VARARGS,
219 xx_foo_doc},
220 {"new", xx_new, METH_VARARGS,
221 PyDoc_STR("new() -> new Xx object")},
222 {NULL, NULL} /* sentinel */
223};
224
225PyDoc_STRVAR(module_doc,
226"This is a template module just for instruction.");
227
228/* Initialization function for the module (*must* be called PyInit_xx) */
229
230
231static struct PyModuleDef xxmodule = {
232 PyModuleDef_HEAD_INIT,
233 "xx",
234 module_doc,
235 -1,
236 xx_methods,
237 NULL,
238 NULL,
239 NULL,
240 NULL
241};
242
243PyMODINIT_FUNC
244PyInit_xxlimited(void)
245{
246 PyObject *m = NULL;
247 PyObject *o;
248
249 /* Due to cross platform compiler issues the slots must be filled
250 * here. It's required for portability to Windows without requiring
251 * C++. */
252 Null_Type_slots[0].pfunc = &PyBaseObject_Type;
253 Null_Type_slots[1].pfunc = PyType_GenericNew;
254 Str_Type_slots[0].pfunc = &PyUnicode_Type;
255
256 Xxo_Type = PyType_FromSpec(&Xxo_Type_spec);
257 if (Xxo_Type == NULL)
258 goto fail;
259
260 /* Create the module and add the functions */
261 m = PyModule_Create(&xxmodule);
262 if (m == NULL)
263 goto fail;
264
265 /* Add some symbolic constants to the module */
266 if (ErrorObject == NULL) {
267 ErrorObject = PyErr_NewException("xx.error", NULL, NULL);
268 if (ErrorObject == NULL)
269 goto fail;
270 }
271 Py_INCREF(ErrorObject);
272 PyModule_AddObject(m, "error", ErrorObject);
273
274 /* Add Str */
275 o = PyType_FromSpec(&Str_Type_spec);
276 if (o == NULL)
277 goto fail;
278 PyModule_AddObject(m, "Str", o);
279
280 /* Add Null */
281 o = PyType_FromSpec(&Null_Type_spec);
282 if (o == NULL)
283 goto fail;
284 PyModule_AddObject(m, "Null", o);
285 return m;
286 fail:
287 Py_XDECREF(m);
288 return NULL;
289}