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