blob: 09e87355b91afa2e987f56e1506c2ad667860991 [file] [log] [blame]
Antoine Pitrou1d80a562018-04-07 18:14:03 +02001#include <Python.h>
2#include "structmember.h"
3
4typedef struct {
5 PyObject_HEAD
6 PyObject *first; /* first name */
7 PyObject *last; /* last name */
8 int number;
9} CustomObject;
10
11static void
12Custom_dealloc(CustomObject *self)
13{
14 Py_XDECREF(self->first);
15 Py_XDECREF(self->last);
16 Py_TYPE(self)->tp_free((PyObject *) self);
17}
18
19static PyObject *
20Custom_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
40static int
41Custom_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
66static PyMemberDef Custom_members[] = {
67 {"number", T_INT, offsetof(CustomObject, number), 0,
68 "custom number"},
69 {NULL} /* Sentinel */
70};
71
72static PyObject *
73Custom_getfirst(CustomObject *self, void *closure)
74{
75 Py_INCREF(self->first);
76 return self->first;
77}
78
79static int
80Custom_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
99static PyObject *
100Custom_getlast(CustomObject *self, void *closure)
101{
102 Py_INCREF(self->last);
103 return self->last;
104}
105
106static int
107Custom_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
126static 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
134static PyObject *
135Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
136{
137 return PyUnicode_FromFormat("%S %S", self->first, self->last);
138}
139
140static 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
147static 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
162static 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
169PyMODINIT_FUNC
170PyInit_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}