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