470,849 Members | 848 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,849 developers. It's quick & easy.

Adding "proxy" functions to a type

Hello all.

Is there a convenient scheme within a C extension to add
methods to a type in such a way as to allow me to
transparently add a "proxy" around them? For example:

typedef PyObject* (*PyMethodCall)(PyObject*, PyObject*);

PyObject* middleMan(PyObject* self, PyObject* args) {
printf("Before call to wrapped funct\n");
PyMethodCall actualFunc = getRealFunction(...);
PyObject* retval = actualFunc(self, args);
printf("After call to wrapped func\n");
return retval;
}

void addMethod(PyTypeObject* t, PyMethodCall* m,
char* name, char* doc) {
// code to forward calls to "middleMan" while putting the
// pointer to "m" somewhere convenient
...
}

My current solution is cumbersome and involves adding a
special field to the PyObject associated with my type, a
custom tp_getattro function and the "middleMan" function:

struct MyPyObj {
PyObject_HEAD
PyMethodCall realfunc;
};

// when adding the method def for "m" instead of pointing it to
// the given function, I point it to the middle man and save
// the "m" function somewhere I can find it later.
void addMethod(PyTypeObject* t, PyMethodCall m,
char* name, char* doc) {

PyMethodDef* def = allocPyMethodDef(t, name);
def->ml_name = name;
def->ml_doc = doc;
def->ml_meth = middleMan;
def->ml_flags = METH_VARARGS;

saveTargetFunction(name, m);
// note I add these here so that documentation is
// available within the interpreter
PyObject* methobj = PyDescr_NewMethod(t, def);
PyDict_SetItemString(t->tp_dict, def->ml_name, methobj);
Py_DECREF(methobj);
}

// when the interpreter does a lookup on an instance of my
// type I set the "realfunc" member of my PyObject and return
// a bound method (which will call into middleMan).
PyObject* customGetaAttro(PyObject* self, PyObject* name) {
MyPyObj* rself = (MyPyObj*)self;
rself->realfunc = findSavedTargetFunc(name);
PyMethodDef* mdef = getMethodDef(self->ob_type, name);
return PyCFunction_New(def, self);
}

// finally, when the middle man is called it extracts the "real"
// function from self and calls that.
PyObject* middleMan(PyObject* self, PyObject* args) {
MyPyObj* rself = (MyPyObj*)(self);
printf("pre call\n");
PyObject* rv = rself->realfunc(rself->obj, args);
printf("post call\n");
rself->realfunc = 0;
return rv;
}

The problem here is that this doesn't work for static functions which
lack a self argument, or for module level functions.

Is there a better way?

Thanks,
Iker Arizmendi

Jul 19 '05 #1
0 1084

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Tomas Christiansen | last post: by
reply views Thread by Henrik Gøttig | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.