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 19static PyObject *ErrorObject; 20 21typedef struct { 22 PyObject_HEAD 23 PyObject *x_attr; /* Attributes dictionary */ 24} XxoObject; 25 26static PyTypeObject Xxo_Type; 27 28#define XxoObject_Check(v) Py_IS_TYPE(v, &Xxo_Type) 29 30static XxoObject * 31newXxoObject(PyObject *arg) 32{ 33 XxoObject *self; 34 self = PyObject_New(XxoObject, &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_Free(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_GetItemWithError(self->x_attr, name); 70 if (v != NULL) { 71 Py_INCREF(v); 72 return v; 73 } 74 else if (PyErr_Occurred()) { 75 return NULL; 76 } 77 } 78 return PyObject_GenericGetAttr((PyObject *)self, name); 79} 80 81static int 82Xxo_setattr(XxoObject *self, const char *name, PyObject *v) 83{ 84 if (self->x_attr == NULL) { 85 self->x_attr = PyDict_New(); 86 if (self->x_attr == NULL) 87 return -1; 88 } 89 if (v == NULL) { 90 int rv = PyDict_DelItemString(self->x_attr, name); 91 if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) 92 PyErr_SetString(PyExc_AttributeError, 93 "delete non-existing Xxo attribute"); 94 return rv; 95 } 96 else 97 return PyDict_SetItemString(self->x_attr, name, v); 98} 99 100static PyTypeObject Xxo_Type = { 101 /* The ob_type field must be initialized in the module init function 102 * to be portable to Windows without using C++. */ 103 PyVarObject_HEAD_INIT(NULL, 0) 104 "xxmodule.Xxo", /*tp_name*/ 105 sizeof(XxoObject), /*tp_basicsize*/ 106 0, /*tp_itemsize*/ 107 /* methods */ 108 (destructor)Xxo_dealloc, /*tp_dealloc*/ 109 0, /*tp_vectorcall_offset*/ 110 (getattrfunc)0, /*tp_getattr*/ 111 (setattrfunc)Xxo_setattr, /*tp_setattr*/ 112 0, /*tp_as_async*/ 113 0, /*tp_repr*/ 114 0, /*tp_as_number*/ 115 0, /*tp_as_sequence*/ 116 0, /*tp_as_mapping*/ 117 0, /*tp_hash*/ 118 0, /*tp_call*/ 119 0, /*tp_str*/ 120 (getattrofunc)Xxo_getattro, /*tp_getattro*/ 121 0, /*tp_setattro*/ 122 0, /*tp_as_buffer*/ 123 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 124 0, /*tp_doc*/ 125 0, /*tp_traverse*/ 126 0, /*tp_clear*/ 127 0, /*tp_richcompare*/ 128 0, /*tp_weaklistoffset*/ 129 0, /*tp_iter*/ 130 0, /*tp_iternext*/ 131 Xxo_methods, /*tp_methods*/ 132 0, /*tp_members*/ 133 0, /*tp_getset*/ 134 0, /*tp_base*/ 135 0, /*tp_dict*/ 136 0, /*tp_descr_get*/ 137 0, /*tp_descr_set*/ 138 0, /*tp_dictoffset*/ 139 0, /*tp_init*/ 140 0, /*tp_alloc*/ 141 0, /*tp_new*/ 142 0, /*tp_free*/ 143 0, /*tp_is_gc*/ 144}; 145/* --------------------------------------------------------------------- */ 146 147/* Function of two integers returning integer */ 148 149PyDoc_STRVAR(xx_foo_doc, 150"foo(i,j)\n\ 151\n\ 152Return the sum of i and j."); 153 154static PyObject * 155xx_foo(PyObject *self, PyObject *args) 156{ 157 long i, j; 158 long res; 159 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) 160 return NULL; 161 res = i+j; /* XXX Do something here */ 162 return PyLong_FromLong(res); 163} 164 165 166/* Function of no arguments returning new Xxo object */ 167 168static PyObject * 169xx_new(PyObject *self, PyObject *args) 170{ 171 XxoObject *rv; 172 173 if (!PyArg_ParseTuple(args, ":new")) 174 return NULL; 175 rv = newXxoObject(args); 176 if (rv == NULL) 177 return NULL; 178 return (PyObject *)rv; 179} 180 181/* Example with subtle bug from extensions manual ("Thin Ice"). */ 182 183static PyObject * 184xx_bug(PyObject *self, PyObject *args) 185{ 186 PyObject *list, *item; 187 188 if (!PyArg_ParseTuple(args, "O:bug", &list)) 189 return NULL; 190 191 item = PyList_GetItem(list, 0); 192 /* Py_INCREF(item); */ 193 PyList_SetItem(list, 1, PyLong_FromLong(0L)); 194 PyObject_Print(item, stdout, 0); 195 printf("\n"); 196 /* Py_DECREF(item); */ 197 198 Py_INCREF(Py_None); 199 return Py_None; 200} 201 202/* Test bad format character */ 203 204static PyObject * 205xx_roj(PyObject *self, PyObject *args) 206{ 207 PyObject *a; 208 long b; 209 if (!PyArg_ParseTuple(args, "O#:roj", &a, &b)) 210 return NULL; 211 Py_INCREF(Py_None); 212 return Py_None; 213} 214 215 216/* ---------- */ 217 218static PyTypeObject Str_Type = { 219 /* The ob_type field must be initialized in the module init function 220 * to be portable to Windows without using C++. */ 221 PyVarObject_HEAD_INIT(NULL, 0) 222 "xxmodule.Str", /*tp_name*/ 223 0, /*tp_basicsize*/ 224 0, /*tp_itemsize*/ 225 /* methods */ 226 0, /*tp_dealloc*/ 227 0, /*tp_vectorcall_offset*/ 228 0, /*tp_getattr*/ 229 0, /*tp_setattr*/ 230 0, /*tp_as_async*/ 231 0, /*tp_repr*/ 232 0, /*tp_as_number*/ 233 0, /*tp_as_sequence*/ 234 0, /*tp_as_mapping*/ 235 0, /*tp_hash*/ 236 0, /*tp_call*/ 237 0, /*tp_str*/ 238 0, /*tp_getattro*/ 239 0, /*tp_setattro*/ 240 0, /*tp_as_buffer*/ 241 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 242 0, /*tp_doc*/ 243 0, /*tp_traverse*/ 244 0, /*tp_clear*/ 245 0, /*tp_richcompare*/ 246 0, /*tp_weaklistoffset*/ 247 0, /*tp_iter*/ 248 0, /*tp_iternext*/ 249 0, /*tp_methods*/ 250 0, /*tp_members*/ 251 0, /*tp_getset*/ 252 0, /* see PyInit_xx */ /*tp_base*/ 253 0, /*tp_dict*/ 254 0, /*tp_descr_get*/ 255 0, /*tp_descr_set*/ 256 0, /*tp_dictoffset*/ 257 0, /*tp_init*/ 258 0, /*tp_alloc*/ 259 0, /*tp_new*/ 260 0, /*tp_free*/ 261 0, /*tp_is_gc*/ 262}; 263 264/* ---------- */ 265 266static PyObject * 267null_richcompare(PyObject *self, PyObject *other, int op) 268{ 269 Py_INCREF(Py_NotImplemented); 270 return Py_NotImplemented; 271} 272 273static PyTypeObject Null_Type = { 274 /* The ob_type field must be initialized in the module init function 275 * to be portable to Windows without using C++. */ 276 PyVarObject_HEAD_INIT(NULL, 0) 277 "xxmodule.Null", /*tp_name*/ 278 0, /*tp_basicsize*/ 279 0, /*tp_itemsize*/ 280 /* methods */ 281 0, /*tp_dealloc*/ 282 0, /*tp_vectorcall_offset*/ 283 0, /*tp_getattr*/ 284 0, /*tp_setattr*/ 285 0, /*tp_as_async*/ 286 0, /*tp_repr*/ 287 0, /*tp_as_number*/ 288 0, /*tp_as_sequence*/ 289 0, /*tp_as_mapping*/ 290 0, /*tp_hash*/ 291 0, /*tp_call*/ 292 0, /*tp_str*/ 293 0, /*tp_getattro*/ 294 0, /*tp_setattro*/ 295 0, /*tp_as_buffer*/ 296 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 297 0, /*tp_doc*/ 298 0, /*tp_traverse*/ 299 0, /*tp_clear*/ 300 null_richcompare, /*tp_richcompare*/ 301 0, /*tp_weaklistoffset*/ 302 0, /*tp_iter*/ 303 0, /*tp_iternext*/ 304 0, /*tp_methods*/ 305 0, /*tp_members*/ 306 0, /*tp_getset*/ 307 0, /* see PyInit_xx */ /*tp_base*/ 308 0, /*tp_dict*/ 309 0, /*tp_descr_get*/ 310 0, /*tp_descr_set*/ 311 0, /*tp_dictoffset*/ 312 0, /*tp_init*/ 313 0, /*tp_alloc*/ 314 PyType_GenericNew, /*tp_new*/ 315 0, /*tp_free*/ 316 0, /*tp_is_gc*/ 317}; 318 319 320/* ---------- */ 321 322 323/* List of functions defined in the module */ 324 325static PyMethodDef xx_methods[] = { 326 {"roj", xx_roj, METH_VARARGS, 327 PyDoc_STR("roj(a,b) -> None")}, 328 {"foo", xx_foo, METH_VARARGS, 329 xx_foo_doc}, 330 {"new", xx_new, METH_VARARGS, 331 PyDoc_STR("new() -> new Xx object")}, 332 {"bug", xx_bug, METH_VARARGS, 333 PyDoc_STR("bug(o) -> None")}, 334 {NULL, NULL} /* sentinel */ 335}; 336 337PyDoc_STRVAR(module_doc, 338"This is a template module just for instruction."); 339 340 341static int 342xx_exec(PyObject *m) 343{ 344 /* Slot initialization is subject to the rules of initializing globals. 345 C99 requires the initializers to be "address constants". Function 346 designators like 'PyType_GenericNew', with implicit conversion to 347 a pointer, are valid C99 address constants. 348 349 However, the unary '&' operator applied to a non-static variable 350 like 'PyBaseObject_Type' is not required to produce an address 351 constant. Compilers may support this (gcc does), MSVC does not. 352 353 Both compilers are strictly standard conforming in this particular 354 behavior. 355 */ 356 Null_Type.tp_base = &PyBaseObject_Type; 357 Str_Type.tp_base = &PyUnicode_Type; 358 359 /* Finalize the type object including setting type of the new type 360 * object; doing it here is required for portability, too. */ 361 if (PyType_Ready(&Xxo_Type) < 0) { 362 return -1; 363 } 364 365 /* Add some symbolic constants to the module */ 366 if (ErrorObject == NULL) { 367 ErrorObject = PyErr_NewException("xx.error", NULL, NULL); 368 if (ErrorObject == NULL) { 369 return -1; 370 } 371 } 372 int rc = PyModule_AddType(m, (PyTypeObject *)ErrorObject); 373 Py_DECREF(ErrorObject); 374 if (rc < 0) { 375 return -1; 376 } 377 378 /* Add Str and Null types */ 379 if (PyModule_AddType(m, &Str_Type) < 0) { 380 return -1; 381 } 382 if (PyModule_AddType(m, &Null_Type) < 0) { 383 return -1; 384 } 385 386 return 0; 387} 388 389static struct PyModuleDef_Slot xx_slots[] = { 390 {Py_mod_exec, xx_exec}, 391 {0, NULL}, 392}; 393 394static struct PyModuleDef xxmodule = { 395 PyModuleDef_HEAD_INIT, 396 "xx", 397 module_doc, 398 0, 399 xx_methods, 400 xx_slots, 401 NULL, 402 NULL, 403 NULL 404}; 405 406/* Export function for the module (*must* be called PyInit_xx) */ 407 408PyMODINIT_FUNC 409PyInit_xx(void) 410{ 411 return PyModuleDef_Init(&xxmodule); 412} 413