#ifndef _EXTENSION2_H_ #define _EXTENSION2_H_ typedef struct { PyObject_HEAD PyObject* first; /* first name */ PyObject* last; /* last name */ int number; } CustomObject; static void Custom_dealloc(CustomObject* self) { Py_XDECREF(self->first); Py_XDECREF(self->last); Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* Custom_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { CustomObject* self; self = (CustomObject*)type->tp_alloc(type, 0); if (self != NULL) { self->first = PyUnicode_FromString(""); if (self->first == NULL) { Py_DECREF(self); return NULL; } self->last = PyUnicode_FromString(""); if (self->last == NULL) { Py_DECREF(self); return NULL; } self->number = 0; } return (PyObject*)self; } static int Custom_init(CustomObject* self, PyObject* args, PyObject* kwds) { static char* kwlist[] = { "first", "last", "number", NULL }; PyObject* first = NULL, * last = NULL, * tmp; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist, &first, &last, &self->number)) return -1; if (first) { tmp = self->first; Py_INCREF(first); self->first = first; Py_DECREF(tmp); } if (last) { tmp = self->last; Py_INCREF(last); self->last = last; Py_DECREF(tmp); } return 0; } static PyMemberDef Custom_members[] = { {"number", T_INT, offsetof(CustomObject, number), 0, "custom number"}, {NULL} /* Sentinel */ }; static PyObject* Custom_getfirst(CustomObject* self, void* closure) { Py_INCREF(self->first); return self->first; } static int Custom_setfirst(CustomObject* self, PyObject* value, void* closure) { PyObject* tmp; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); return -1; } if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "The first attribute value must be a string"); return -1; } tmp = self->first; Py_INCREF(value); self->first = value; Py_DECREF(tmp); return 0; } static PyObject* Custom_getlast(CustomObject* self, void* closure) { Py_INCREF(self->last); return self->last; } static int Custom_setlast(CustomObject* self, PyObject* value, void* closure) { PyObject* tmp; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); return -1; } if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "The last attribute value must be a string"); return -1; } tmp = self->last; Py_INCREF(value); self->last = value; Py_DECREF(tmp); return 0; } static PyGetSetDef Custom_getsetters[] = { {"first", (getter)Custom_getfirst, (setter)Custom_setfirst, "first name", NULL}, {"last", (getter)Custom_getlast, (setter)Custom_setlast, "last name", NULL}, {NULL} /* Sentinel */ }; static PyObject* Custom_name(CustomObject* self, PyObject* Py_UNUSED(ignored)) { return PyUnicode_FromFormat("%S %S", self->first, self->last); } static PyMethodDef Custom_methods[] = { {"name", (PyCFunction)Custom_name, METH_NOARGS, "Return the name, combining the first and last name" }, {NULL} /* Sentinel */ }; static PyTypeObject CustomType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "example.Custom", .tp_doc = "Custom objects", .tp_basicsize = sizeof(CustomObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_new = Custom_new, .tp_init = (initproc)Custom_init, .tp_dealloc = (destructor)Custom_dealloc, .tp_members = Custom_members, .tp_methods = Custom_methods, .tp_getset = Custom_getsetters, }; #endif