Home | History | Annotate | Download | only in includes
      1 #include <Python.h>
      2 #include "structmember.h"
      3 
      4 typedef struct {
      5     PyObject_HEAD
      6     PyObject *first;
      7     PyObject *last;
      8     int number;
      9 } Noddy;
     10 
     11 static void
     12 Noddy_dealloc(Noddy* self)
     13 {
     14     Py_XDECREF(self->first);
     15     Py_XDECREF(self->last);
     16     Py_TYPE(self)->tp_free((PyObject*)self);
     17 }
     18 
     19 static PyObject *
     20 Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     21 {
     22     Noddy *self;
     23 
     24     self = (Noddy *)type->tp_alloc(type, 0);
     25     if (self != NULL) {
     26         self->first = PyUnicode_FromString("");
     27         if (self->first == NULL) {
     28             Py_DECREF(self);
     29             return NULL;
     30         }
     31 
     32         self->last = PyUnicode_FromString("");
     33         if (self->last == NULL) {
     34             Py_DECREF(self);
     35             return NULL;
     36         }
     37 
     38         self->number = 0;
     39     }
     40 
     41     return (PyObject *)self;
     42 }
     43 
     44 static int
     45 Noddy_init(Noddy *self, PyObject *args, PyObject *kwds)
     46 {
     47     PyObject *first=NULL, *last=NULL, *tmp;
     48 
     49     static char *kwlist[] = {"first", "last", "number", NULL};
     50 
     51     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|SSi", kwlist,
     52                                       &first, &last,
     53                                       &self->number))
     54         return -1;
     55 
     56     if (first) {
     57         tmp = self->first;
     58         Py_INCREF(first);
     59         self->first = first;
     60         Py_DECREF(tmp);
     61     }
     62 
     63     if (last) {
     64         tmp = self->last;
     65         Py_INCREF(last);
     66         self->last = last;
     67         Py_DECREF(tmp);
     68     }
     69 
     70     return 0;
     71 }
     72 
     73 static PyMemberDef Noddy_members[] = {
     74     {"number", T_INT, offsetof(Noddy, number), 0,
     75      "noddy number"},
     76     {NULL}  /* Sentinel */
     77 };
     78 
     79 static PyObject *
     80 Noddy_getfirst(Noddy *self, void *closure)
     81 {
     82     Py_INCREF(self->first);
     83     return self->first;
     84 }
     85 
     86 static int
     87 Noddy_setfirst(Noddy *self, PyObject *value, void *closure)
     88 {
     89     if (value == NULL) {
     90         PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
     91         return -1;
     92     }
     93 
     94     if (! PyUnicode_Check(value)) {
     95         PyErr_SetString(PyExc_TypeError,
     96                         "The first attribute value must be a string");
     97         return -1;
     98     }
     99 
    100     Py_DECREF(self->first);
    101     Py_INCREF(value);
    102     self->first = value;
    103 
    104     return 0;
    105 }
    106 
    107 static PyObject *
    108 Noddy_getlast(Noddy *self, void *closure)
    109 {
    110     Py_INCREF(self->last);
    111     return self->last;
    112 }
    113 
    114 static int
    115 Noddy_setlast(Noddy *self, PyObject *value, void *closure)
    116 {
    117     if (value == NULL) {
    118         PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
    119         return -1;
    120     }
    121 
    122     if (! PyUnicode_Check(value)) {
    123         PyErr_SetString(PyExc_TypeError,
    124                         "The last attribute value must be a string");
    125         return -1;
    126     }
    127 
    128     Py_DECREF(self->last);
    129     Py_INCREF(value);
    130     self->last = value;
    131 
    132     return 0;
    133 }
    134 
    135 static PyGetSetDef Noddy_getseters[] = {
    136     {"first",
    137      (getter)Noddy_getfirst, (setter)Noddy_setfirst,
    138      "first name",
    139      NULL},
    140     {"last",
    141      (getter)Noddy_getlast, (setter)Noddy_setlast,
    142      "last name",
    143      NULL},
    144     {NULL}  /* Sentinel */
    145 };
    146 
    147 static PyObject *
    148 Noddy_name(Noddy* self)
    149 {
    150     return PyUnicode_FromFormat("%S %S", self->first, self->last);
    151 }
    152 
    153 static PyMethodDef Noddy_methods[] = {
    154     {"name", (PyCFunction)Noddy_name, METH_NOARGS,
    155      "Return the name, combining the first and last name"
    156     },
    157     {NULL}  /* Sentinel */
    158 };
    159 
    160 static PyTypeObject NoddyType = {
    161     PyVarObject_HEAD_INIT(NULL, 0)
    162     "noddy.Noddy",             /* tp_name */
    163     sizeof(Noddy),             /* tp_basicsize */
    164     0,                         /* tp_itemsize */
    165     (destructor)Noddy_dealloc, /* tp_dealloc */
    166     0,                         /* tp_print */
    167     0,                         /* tp_getattr */
    168     0,                         /* tp_setattr */
    169     0,                         /* tp_reserved */
    170     0,                         /* tp_repr */
    171     0,                         /* tp_as_number */
    172     0,                         /* tp_as_sequence */
    173     0,                         /* tp_as_mapping */
    174     0,                         /* tp_hash  */
    175     0,                         /* tp_call */
    176     0,                         /* tp_str */
    177     0,                         /* tp_getattro */
    178     0,                         /* tp_setattro */
    179     0,                         /* tp_as_buffer */
    180     Py_TPFLAGS_DEFAULT |
    181         Py_TPFLAGS_BASETYPE,   /* tp_flags */
    182     "Noddy objects",           /* tp_doc */
    183     0,                         /* tp_traverse */
    184     0,                         /* tp_clear */
    185     0,                         /* tp_richcompare */
    186     0,                         /* tp_weaklistoffset */
    187     0,                         /* tp_iter */
    188     0,                         /* tp_iternext */
    189     Noddy_methods,             /* tp_methods */
    190     Noddy_members,             /* tp_members */
    191     Noddy_getseters,           /* tp_getset */
    192     0,                         /* tp_base */
    193     0,                         /* tp_dict */
    194     0,                         /* tp_descr_get */
    195     0,                         /* tp_descr_set */
    196     0,                         /* tp_dictoffset */
    197     (initproc)Noddy_init,      /* tp_init */
    198     0,                         /* tp_alloc */
    199     Noddy_new,                 /* tp_new */
    200 };
    201 
    202 static PyModuleDef noddy3module = {
    203     PyModuleDef_HEAD_INIT,
    204     "noddy3",
    205     "Example module that creates an extension type.",
    206     -1,
    207     NULL, NULL, NULL, NULL, NULL
    208 };
    209 
    210 PyMODINIT_FUNC
    211 PyInit_noddy3(void)
    212 {
    213     PyObject* m;
    214 
    215     if (PyType_Ready(&NoddyType) < 0)
    216         return NULL;
    217 
    218     m = PyModule_Create(&noddy3module);
    219     if (m == NULL)
    220         return NULL;
    221 
    222     Py_INCREF(&NoddyType);
    223     PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType);
    224     return m;
    225 }
    226