• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 void
Custom_dealloc(CustomObject * self)13 Custom_dealloc(CustomObject *self)
14 {
15     Py_XDECREF(self->first);
16     Py_XDECREF(self->last);
17     Py_TYPE(self)->tp_free((PyObject *) self);
18 }
19 
20 static PyObject *
Custom_new(PyTypeObject * type,PyObject * args,PyObject * kwds)21 Custom_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 
41 static int
Custom_init(CustomObject * self,PyObject * args,PyObject * kwds)42 Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
43 {
44     static char *kwlist[] = {"first", "last", "number", NULL};
45     PyObject *first = NULL, *last = NULL;
46 
47     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
48                                      &first, &last,
49                                      &self->number))
50         return -1;
51 
52     if (first) {
53         Py_XSETREF(self->first, Py_NewRef(first));
54     }
55     if (last) {
56         Py_XSETREF(self->last, Py_NewRef(last));
57     }
58     return 0;
59 }
60 
61 static PyMemberDef Custom_members[] = {
62     {"first", Py_T_OBJECT_EX, offsetof(CustomObject, first), 0,
63      "first name"},
64     {"last", Py_T_OBJECT_EX, offsetof(CustomObject, last), 0,
65      "last name"},
66     {"number", Py_T_INT, offsetof(CustomObject, number), 0,
67      "custom number"},
68     {NULL}  /* Sentinel */
69 };
70 
71 static PyObject *
Custom_name(CustomObject * self,PyObject * Py_UNUSED (ignored))72 Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
73 {
74     if (self->first == NULL) {
75         PyErr_SetString(PyExc_AttributeError, "first");
76         return NULL;
77     }
78     if (self->last == NULL) {
79         PyErr_SetString(PyExc_AttributeError, "last");
80         return NULL;
81     }
82     return PyUnicode_FromFormat("%S %S", self->first, self->last);
83 }
84 
85 static PyMethodDef Custom_methods[] = {
86     {"name", (PyCFunction) Custom_name, METH_NOARGS,
87      "Return the name, combining the first and last name"
88     },
89     {NULL}  /* Sentinel */
90 };
91 
92 static PyTypeObject CustomType = {
93     .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
94     .tp_name = "custom2.Custom",
95     .tp_doc = PyDoc_STR("Custom objects"),
96     .tp_basicsize = sizeof(CustomObject),
97     .tp_itemsize = 0,
98     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
99     .tp_new = Custom_new,
100     .tp_init = (initproc) Custom_init,
101     .tp_dealloc = (destructor) Custom_dealloc,
102     .tp_members = Custom_members,
103     .tp_methods = Custom_methods,
104 };
105 
106 static PyModuleDef custommodule = {
107     .m_base =PyModuleDef_HEAD_INIT,
108     .m_name = "custom2",
109     .m_doc = "Example module that creates an extension type.",
110     .m_size = -1,
111 };
112 
113 PyMODINIT_FUNC
PyInit_custom2(void)114 PyInit_custom2(void)
115 {
116     PyObject *m;
117     if (PyType_Ready(&CustomType) < 0)
118         return NULL;
119 
120     m = PyModule_Create(&custommodule);
121     if (m == NULL)
122         return NULL;
123 
124     if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
125         Py_DECREF(m);
126         return NULL;
127     }
128 
129     return m;
130 }
131