[vtk-developers] Modification to vtkPythonUtil to support passing of void *callData
Charl P. Botha
c.p.botha at its.tudelft.nl
Fri Mar 14 12:29:48 EST 2003
Dear developers and especially David and Prabhu,
As you know, the Python wrapping does not pass the void *callData of the
vtkPythonCommand->Execute() through to Python for very obvious reasons: it's
very difficult to determine the type of this parameter at run-time.
This means that no Python observer can query the callData parameter, so, for
example, a Python program can not determine the error message when catching
an ErrorEvent.
I've made changes to vtkPythonUtil.{cxx,h} that attempt to remedy this
situation, but are entirely backwards compatible. I'll illustrate with an
example:
### this is the traditional way and still works...
def handlerOne(theObject, eventname):
# durn, we don't know what the error was!
print eventname
someVtkObject.AddObserver('ErrorEvent', handlerOne)
### this is the new way:
def handlerOne(theObject, eventname, errorMessage):
# if my code can't convert callData to a string, errorMessage will
# be None
print errorMessage
# we KNOW that an ErrorEvent passes a null-terminated string
handlerOne.callDataType = "string0"
someVtkObject.AddObserver('ErrorEvent', handlerOne)
### END EXAMPLE
At the moment, I've only implemented the "string0" type, but others can be
easily added within my framework. I would very much like to commit this
patch, as I desperately need the functionality, but will obviously only do
this with the approval of the VTK Python Pantheon. I've attached the patch
for your review.
Thanks,
Charl
--
charl p. botha http://cpbotha.net/ http://visualisation.tudelft.nl/
-------------- next part --------------
Index: vtkPythonUtil.cxx
===================================================================
RCS file: /vtk/cvsroot/VTK/Common/vtkPythonUtil.cxx,v
retrieving revision 1.56
diff -u -r1.56 vtkPythonUtil.cxx
--- vtkPythonUtil.cxx 12 Mar 2003 14:35:29 -0000 1.56
+++ vtkPythonUtil.cxx 14 Mar 2003 16:19:55 -0000
@@ -1735,8 +1735,8 @@
this->obj = o;
}
-void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype,
- void *)
+void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype,
+ void *callData)
{
PyObject *arglist, *result, *obj2;
const char *eventname;
@@ -1753,7 +1753,66 @@
eventname = this->GetStringFromEventId(eventtype);
- arglist = Py_BuildValue("(Ns)",obj2,eventname);
+ // extension by Charl P. Botha so that callData is available from Python:
+ // * callData used to be ignored completely: this is not entirely desirable,
+ // e.g. with catching ErrorEvent
+ // * I have extended this code so that callData can be caught whilst not
+ // affecting any existing VTK Python code
+ // * make sure your observer python function has a callDataType string
+ // attribute that describes how callData should be passed through, e.g.:
+ // def handler(theObject, eventType, message):
+ // print "Error: %s" % (message)
+ // # we know that ErrorEvent passes a null-terminated string
+ // handler.callDataType = "string0"
+ // someObject.AddObserver('ErrorEvent', handler)
+ //
+ PyObject *callDataTypeObj = PyObject_GetAttrString(this->obj, "callDataType");
+ char *callDataTypeString = NULL;
+ if (callDataTypeObj)
+ {
+ callDataTypeString = PyString_AsString(callDataTypeObj);
+ if (callDataTypeString)
+ {
+ if (strcmp(callDataTypeString, "string0") == 0)
+ {
+ // this means the user wants the callData cast as a string
+ PyObject* callDataAsString = PyString_FromString((char*)callData);
+ if (callDataAsString)
+ {
+ arglist = Py_BuildValue("(NsN)", obj2, eventname, callDataAsString);
+ }
+ else
+ {
+ PyErr_Clear();
+ // we couldn't create a string, so we pass in None
+ Py_INCREF(Py_None);
+ arglist = Py_BuildValue("(NsN)", obj2, eventname, Py_None);
+ }
+ }
+ else
+ {
+ // we don't handle this, so we pass in a None as the third parameter
+ Py_INCREF(Py_None);
+ arglist = Py_BuildValue("(NsN)", obj2, eventname, Py_None);
+ }
+ }
+ else
+ {
+ // the handler object has a callDataType attribute, but it's not a
+ // string -- then we do traditional arguments
+ arglist = Py_BuildValue("(Ns)",obj2,eventname);
+ }
+
+ // we have to do this
+ Py_DECREF(callDataTypeObj);
+ }
+ else
+ {
+ // this means there was no callDataType attribute, so we do the
+ // traditional obj(object, eventname) call
+ PyErr_Clear();
+ arglist = Py_BuildValue("(Ns)",obj2,eventname);
+ }
result = PyEval_CallObject(this->obj, arglist);
Py_DECREF(arglist);
Index: vtkPythonUtil.h
===================================================================
RCS file: /vtk/cvsroot/VTK/Common/vtkPythonUtil.h,v
retrieving revision 1.28
diff -u -r1.28 vtkPythonUtil.h
--- vtkPythonUtil.h 16 Jul 2002 21:17:33 -0000 1.28
+++ vtkPythonUtil.h 14 Mar 2003 16:19:56 -0000
@@ -164,7 +164,7 @@
static vtkPythonCommand *New() { return new vtkPythonCommand; };
void SetObject(PyObject *o);
- void Execute(vtkObject *ptr, unsigned long eventtype, void *);
+ void Execute(vtkObject *ptr, unsigned long eventtype, void *callData);
PyObject *obj;
protected:
More information about the vtk-developers
mailing list