A
Aaron Brady
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;
}
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;
}