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