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