subclass PyDictObject -- any gotchas?

Aaron Brady castironpi at gmail.com
Thu Jan 22 08:49:30 EST 2009


Hello all,

I am trying to create a mapping class similar to the base dictionary,
but with some added behaviors that affect pointers on a low level.  I
have a bare-bones version I compiled with MinGW, and it is working!  I
want to know if there is anything that is going to bite me later, when
I start adding real behavior: for example, times when my overrides
won't get called, shortcuts, better macros, etc.

Later on, I will be altering the 'ma_table' field from one call to
another, overriding most of PyDict_Type's methods with before-and-
after code, adding synchronization, and copying-and-pasting memory
allocation code from 'dictobject.c' directly in, since I need the
object to be at specific addresses.  Anything I need to beware of?
Any reason it might be infeasible?

108 lines, please snip on reply.

Thanks in advance and sincerely,
A. Brady

#include <Python.h>
#include <iostream>
using namespace std;

typedef struct {
    PyDictObject base;
    /* Type-specific fields go here. */

} DictSubObject;

static void
dictsub_dealloc(register PyDictObject *mp) {
    cout<< "In 'dictsub_dealloc'"<< endl;
    PyDict_Type.tp_dealloc((PyObject*)mp);
}

static int
dictsub_ass_sub(DictSubObject *mp, PyObject *v, PyObject *w)
{
    cout<< "In 'dictsub_ass_sub'"<< endl;
    return PyDict_Type.tp_as_mapping->mp_ass_subscript( (PyObject *)
mp, v, w );
}

static PyMappingMethods dictsub_as_mapping = {
    NULL, /*mp_length*/
    NULL, /*mp_subscript*/
    (objobjargproc)dictsub_ass_sub, /*mp_ass_subscript*/
};

static PyMethodDef DictSub_methods[] = {
    {NULL}
};

PyObject *
dictsub_alloc(PyTypeObject *self, Py_ssize_t nitems) {
    cout<< "In 'dictsub_alloc'"<< endl;
    return PyDict_Type.tp_alloc(self, nitems);
}

static PyTypeObject DictSubType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "DictSub",                    /*tp_name*/
    sizeof(DictSubObject),        /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)dictsub_dealloc, /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    &dictsub_as_mapping,        /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT |
      Py_TPFLAGS_BASETYPE,     /*tp_flags*/
    "DictSub objects",          /* tp_doc */
    0,                         /* tp_traverse */
    0,                         /* tp_clear */
    0,                         /* tp_richcompare */
    0,                         /* tp_weaklistoffset */
    0,                         /* tp_iter */
    0,                         /* tp_iternext */
    DictSub_methods,              /* tp_methods */
    0,                         /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    0,                         /* tp_init */
    dictsub_alloc,             /* tp_alloc */
    0,                         /* tp_new */
};

static PyMethodDef module_methods[] = {
    {NULL}  /* Sentinel */
};

#ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initdictsub(void)
{
    PyObject* m;

    DictSubType.tp_base= &PyDict_Type;
    if (PyType_Ready(&DictSubType) < 0)
        return;

    m = Py_InitModule3("dictsub", module_methods,
                       "Custom.");

    Py_INCREF(&DictSubType);
    PyModule_AddObject(m, "DictSub", (PyObject *)&DictSubType);

    if (m == NULL)
      return;

}



More information about the Python-list mailing list