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