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; /* first name */
      7     PyObject *last;  /* last name */
      8     int number;
      9 } CustomObject;
     10 
     11 static int
     12 Custom_traverse(CustomObject *self, visitproc visit, void *arg)
     13 {
     14     Py_VISIT(self->first);
     15     Py_VISIT(self->last);
     16     return 0;
     17 }
     18 
     19 static int
     20 Custom_clear(CustomObject *self)
     21 {
     22     Py_CLEAR(self->first);
     23     Py_CLEAR(self->last);
     24     return 0;
     25 }
     26 
     27 static void
     28 Custom_dealloc(CustomObject *self)
     29 {
     30     PyObject_GC_UnTrack(self);
     31     Custom_clear(self);
     32     Py_TYPE(self)->tp_free((PyObject *) self);
     33 }
     34 
     35 static PyObject *
     36 Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     37 {
     38     CustomObject *self;
     39     self = (CustomObject *) type->tp_alloc(type, 0);
     40     if (self != NULL) {
     41         self->first = PyUnicode_FromString("");
     42         if (self->first == NULL) {
     43             Py_DECREF(self);
     44             return NULL;
     45         }
     46         self->last = PyUnicode_FromString("");
     47         if (self->last == NULL) {
     48             Py_DECREF(self);
     49             return NULL;
     50         }
     51         self->number = 0;
     52     }
     53     return (PyObject *) self;
     54 }
     55 
     56 static int
     57 Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
     58 {
     59     static char *kwlist[] = {"first", "last", "number", NULL};
     60     PyObject *first = NULL, *last = NULL, *tmp;
     61 
     62     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
     63                                      &first, &last,
     64                                      &self->number))
     65         return -1;
     66 
     67     if (first) {
     68         tmp = self->first;
     69         Py_INCREF(first);
     70         self->first = first;
     71         Py_DECREF(tmp);
     72     }
     73     if (last) {
     74         tmp = self->last;
     75         Py_INCREF(last);
     76         self->last = last;
     77         Py_DECREF(tmp);
     78     }
     79     return 0;
     80 }
     81 
     82 static PyMemberDef Custom_members[] = {
     83     {"number", T_INT, offsetof(CustomObject, number), 0,
     84      "custom number"},
     85     {NULL}  /* Sentinel */
     86 };
     87 
     88 static PyObject *
     89 Custom_getfirst(CustomObject *self, void *closure)
     90 {
     91     Py_INCREF(self->first);
     92     return self->first;
     93 }
     94 
     95 static int
     96 Custom_setfirst(CustomObject *self, PyObject *value, void *closure)
     97 {
     98     if (value == NULL) {
     99         PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
    100         return -1;
    101     }
    102     if (!PyUnicode_Check(value)) {
    103         PyErr_SetString(PyExc_TypeError,
    104                         "The first attribute value must be a string");
    105         return -1;
    106     }
    107     Py_INCREF(value);
    108     Py_CLEAR(self->first);
    109     self->first = value;
    110     return 0;
    111 }
    112 
    113 static PyObject *
    114 Custom_getlast(CustomObject *self, void *closure)
    115 {
    116     Py_INCREF(self->last);
    117     return self->last;
    118 }
    119 
    120 static int
    121 Custom_setlast(CustomObject *self, PyObject *value, void *closure)
    122 {
    123     if (value == NULL) {
    124         PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
    125         return -1;
    126     }
    127     if (!PyUnicode_Check(value)) {
    128         PyErr_SetString(PyExc_TypeError,
    129                         "The last attribute value must be a string");
    130         return -1;
    131     }
    132     Py_INCREF(value);
    133     Py_CLEAR(self->last);
    134     self->last = value;
    135     return 0;
    136 }
    137 
    138 static PyGetSetDef Custom_getsetters[] = {
    139     {"first", (getter) Custom_getfirst, (setter) Custom_setfirst,
    140      "first name", NULL},
    141     {"last", (getter) Custom_getlast, (setter) Custom_setlast,
    142      "last name", NULL},
    143     {NULL}  /* Sentinel */
    144 };
    145 
    146 static PyObject *
    147 Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
    148 {
    149     return PyUnicode_FromFormat("%S %S", self->first, self->last);
    150 }
    151 
    152 static PyMethodDef Custom_methods[] = {
    153     {"name", (PyCFunction) Custom_name, METH_NOARGS,
    154      "Return the name, combining the first and last name"
    155     },
    156     {NULL}  /* Sentinel */
    157 };
    158 
    159 static PyTypeObject CustomType = {
    160     PyVarObject_HEAD_INIT(NULL, 0)
    161     .tp_name = "custom4.Custom",
    162     .tp_doc = "Custom objects",
    163     .tp_basicsize = sizeof(CustomObject),
    164     .tp_itemsize = 0,
    165     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
    166     .tp_new = Custom_new,
    167     .tp_init = (initproc) Custom_init,
    168     .tp_dealloc = (destructor) Custom_dealloc,
    169     .tp_traverse = (traverseproc) Custom_traverse,
    170     .tp_clear = (inquiry) Custom_clear,
    171     .tp_members = Custom_members,
    172     .tp_methods = Custom_methods,
    173     .tp_getset = Custom_getsetters,
    174 };
    175 
    176 static PyModuleDef custommodule = {
    177     PyModuleDef_HEAD_INIT,
    178     .m_name = "custom4",
    179     .m_doc = "Example module that creates an extension type.",
    180     .m_size = -1,
    181 };
    182 
    183 PyMODINIT_FUNC
    184 PyInit_custom4(void)
    185 {
    186     PyObject *m;
    187     if (PyType_Ready(&CustomType) < 0)
    188         return NULL;
    189 
    190     m = PyModule_Create(&custommodule);
    191     if (m == NULL)
    192         return NULL;
    193 
    194     Py_INCREF(&CustomType);
    195     PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
    196     return m;
    197 }
    198