1 #include <Python.h>
2 #include "structmember.h"
3
4 typedef struct {
5 PyObject_HEAD
6 PyObject *first; /* first name */
7 PyObject *last; /* last name */
8 int number;
9 } CustomObject;
10
11 static void
Custom_dealloc(CustomObject * self)12 Custom_dealloc(CustomObject *self)
13 {
14 Py_XDECREF(self->first);
15 Py_XDECREF(self->last);
16 Py_TYPE(self)->tp_free((PyObject *) self);
17 }
18
19 static PyObject *
Custom_new(PyTypeObject * type,PyObject * args,PyObject * kwds)20 Custom_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
40 static int
Custom_init(CustomObject * self,PyObject * args,PyObject * kwds)41 Custom_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, "|OOi", 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_XDECREF(tmp);
56 }
57 if (last) {
58 tmp = self->last;
59 Py_INCREF(last);
60 self->last = last;
61 Py_XDECREF(tmp);
62 }
63 return 0;
64 }
65
66 static PyMemberDef Custom_members[] = {
67 {"first", T_OBJECT_EX, offsetof(CustomObject, first), 0,
68 "first name"},
69 {"last", T_OBJECT_EX, offsetof(CustomObject, last), 0,
70 "last name"},
71 {"number", T_INT, offsetof(CustomObject, number), 0,
72 "custom number"},
73 {NULL} /* Sentinel */
74 };
75
76 static PyObject *
Custom_name(CustomObject * self,PyObject * Py_UNUSED (ignored))77 Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
78 {
79 if (self->first == NULL) {
80 PyErr_SetString(PyExc_AttributeError, "first");
81 return NULL;
82 }
83 if (self->last == NULL) {
84 PyErr_SetString(PyExc_AttributeError, "last");
85 return NULL;
86 }
87 return PyUnicode_FromFormat("%S %S", self->first, self->last);
88 }
89
90 static PyMethodDef Custom_methods[] = {
91 {"name", (PyCFunction) Custom_name, METH_NOARGS,
92 "Return the name, combining the first and last name"
93 },
94 {NULL} /* Sentinel */
95 };
96
97 static PyTypeObject CustomType = {
98 PyVarObject_HEAD_INIT(NULL, 0)
99 .tp_name = "custom2.Custom",
100 .tp_doc = "Custom objects",
101 .tp_basicsize = sizeof(CustomObject),
102 .tp_itemsize = 0,
103 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
104 .tp_new = Custom_new,
105 .tp_init = (initproc) Custom_init,
106 .tp_dealloc = (destructor) Custom_dealloc,
107 .tp_members = Custom_members,
108 .tp_methods = Custom_methods,
109 };
110
111 static PyModuleDef custommodule = {
112 PyModuleDef_HEAD_INIT,
113 .m_name = "custom2",
114 .m_doc = "Example module that creates an extension type.",
115 .m_size = -1,
116 };
117
118 PyMODINIT_FUNC
PyInit_custom2(void)119 PyInit_custom2(void)
120 {
121 PyObject *m;
122 if (PyType_Ready(&CustomType) < 0)
123 return NULL;
124
125 m = PyModule_Create(&custommodule);
126 if (m == NULL)
127 return NULL;
128
129 Py_INCREF(&CustomType);
130 PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
131 return m;
132 }
133