• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define PY_SSIZE_T_CLEAN
2 #include <Python.h>
3 #include "structmember.h"
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, *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 
67 static 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 
77 static PyObject *
Custom_name(CustomObject * self,PyObject * Py_UNUSED (ignored))78 Custom_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 
91 static 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 
98 static PyTypeObject CustomType = {
99     PyVarObject_HEAD_INIT(NULL, 0)
100     .tp_name = "custom2.Custom",
101     .tp_doc = "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 
112 static 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 
119 PyMODINIT_FUNC
PyInit_custom2(void)120 PyInit_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