xref: /third_party/python/Doc/includes/custom2.c (revision 7db96d56)
1#define PY_SSIZE_T_CLEAN
2#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, "|OOi", 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_XDECREF(tmp);
57    }
58    if (last) {
59        tmp = self->last;
60        Py_INCREF(last);
61        self->last = last;
62        Py_XDECREF(tmp);
63    }
64    return 0;
65}
66
67static PyMemberDef Custom_members[] = {
68    {"first", T_OBJECT_EX, offsetof(CustomObject, first), 0,
69     "first name"},
70    {"last", T_OBJECT_EX, offsetof(CustomObject, last), 0,
71     "last name"},
72    {"number", T_INT, offsetof(CustomObject, number), 0,
73     "custom number"},
74    {NULL}  /* Sentinel */
75};
76
77static PyObject *
78Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
79{
80    if (self->first == NULL) {
81        PyErr_SetString(PyExc_AttributeError, "first");
82        return NULL;
83    }
84    if (self->last == NULL) {
85        PyErr_SetString(PyExc_AttributeError, "last");
86        return NULL;
87    }
88    return PyUnicode_FromFormat("%S %S", self->first, self->last);
89}
90
91static PyMethodDef Custom_methods[] = {
92    {"name", (PyCFunction) Custom_name, METH_NOARGS,
93     "Return the name, combining the first and last name"
94    },
95    {NULL}  /* Sentinel */
96};
97
98static PyTypeObject CustomType = {
99    PyVarObject_HEAD_INIT(NULL, 0)
100    .tp_name = "custom2.Custom",
101    .tp_doc = PyDoc_STR("Custom objects"),
102    .tp_basicsize = sizeof(CustomObject),
103    .tp_itemsize = 0,
104    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
105    .tp_new = Custom_new,
106    .tp_init = (initproc) Custom_init,
107    .tp_dealloc = (destructor) Custom_dealloc,
108    .tp_members = Custom_members,
109    .tp_methods = Custom_methods,
110};
111
112static PyModuleDef custommodule = {
113    PyModuleDef_HEAD_INIT,
114    .m_name = "custom2",
115    .m_doc = "Example module that creates an extension type.",
116    .m_size = -1,
117};
118
119PyMODINIT_FUNC
120PyInit_custom2(void)
121{
122    PyObject *m;
123    if (PyType_Ready(&CustomType) < 0)
124        return NULL;
125
126    m = PyModule_Create(&custommodule);
127    if (m == NULL)
128        return NULL;
129
130    Py_INCREF(&CustomType);
131    if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
132        Py_DECREF(&CustomType);
133        Py_DECREF(m);
134        return NULL;
135    }
136
137    return m;
138}
139