Home | History | Annotate | Download | only in Modules
      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