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