/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkPythonUtil.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // This include allows VTK to build on some platforms with broken Python // header files. #include "vtkPythonUtil.h" #include "vtkSystemIncludes.h" #include "vtkObject.h" #include "vtkObjectFactory.h" #include "vtkSmartPointerBase.h" #include "vtkTimeStamp.h" #include "vtkWindows.h" #include #include #if defined ( _MSC_VER ) # define vtkConvertPtrToLong(x) ((long)(PtrToUlong(x))) #else # define vtkConvertPtrToLong(x) ((long)(x)) #endif // The following macro is used to supress missing initializer // warnings. Python documentation says these should not be necessary. // We define it as a macro in case the length needs to change across // python versions. #if PY_VERSION_HEX >= 0x02030000 #define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0, #elif PY_VERSION_HEX >= 0x02020000 #define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, #else #define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED #endif //#define VTKPYTHONDEBUG //-------------------------------------------------------------------- // There are two hash tables associated with the Python wrappers class vtkPythonUtil { public: vtkPythonUtil(); ~vtkPythonUtil(); vtkstd::map *ObjectHash; vtkstd::map *ClassHash; }; //-------------------------------------------------------------------- vtkPythonUtil *vtkPythonHash = NULL; //-------------------------------------------------------------------- vtkPythonUtil::vtkPythonUtil() { this->ObjectHash = new vtkstd::map; this->ClassHash = new vtkstd::map;; } //-------------------------------------------------------------------- vtkPythonUtil::~vtkPythonUtil() { delete this->ObjectHash; delete this->ClassHash; } //-------------------------------------------------------------------- extern "C" void vtkPythonHashDelete() { delete vtkPythonHash; vtkPythonHash = 0; } //-------------------------------------------------------------------- static PyObject *PyVTKObject_PyString(PyVTKObject *self) { PyObject *func = PyObject_GetAttrString((PyObject *)self, (char*)"__str__"); if (func) { PyObject *res = PyEval_CallObject(func, (PyObject *)NULL); Py_DECREF(func); return res; } PyErr_Clear(); ostrstream vtkmsg_with_warning_C4701; self->vtk_ptr->Print(vtkmsg_with_warning_C4701); vtkmsg_with_warning_C4701.put('\0'); PyObject *res = PyString_FromString(vtkmsg_with_warning_C4701.str()); vtkmsg_with_warning_C4701.rdbuf()->freeze(0); return res; } //-------------------------------------------------------------------- static PyObject *PyVTKObject_PyRepr(PyVTKObject *self) { PyObject *func = PyObject_GetAttrString((PyObject *)self, (char*)"__repr__"); if (func) { PyObject *res = PyEval_CallObject(func, (PyObject *)NULL); Py_DECREF(func); return res; } PyErr_Clear(); char buf[255]; sprintf(buf,"<%s.%s %s at %p>", PyString_AsString(self->vtk_class->vtk_module), PyString_AsString(self->vtk_class->vtk_name), self->ob_type->tp_name,self); return PyString_FromString(buf); } //-------------------------------------------------------------------- int PyVTKObject_PySetAttr(PyVTKObject *self, PyObject *attr, PyObject *value) { char *name = PyString_AsString(attr); if (name[0] == '_' && name[1] == '_') { if (strcmp(name, "__dict__") == 0) { PyErr_SetString(PyExc_RuntimeError, "__dict__ is a read-only attribute"); return -1; } if (strcmp(name, "__class__") == 0) { PyErr_SetString(PyExc_RuntimeError, "__class__ is a read-only attribute"); return -1; } } if (value) { PyObject *func = self->vtk_class->vtk_setattr; if (func) { PyObject *args = Py_BuildValue((char*)"(OOO)", self, attr, value); PyObject *res = PyEval_CallObject(func, args); Py_DECREF(args); if (res) { Py_DECREF(res); return 0; } return -1; } return PyDict_SetItem(self->vtk_dict, attr, value); } else { PyObject *func = self->vtk_class->vtk_delattr; if (func) { PyObject *args = Py_BuildValue((char*)"(OO)", self, attr); PyObject *res = PyEval_CallObject(func, args); Py_DECREF(args); if (res) { Py_DECREF(res); return 0; } return -1; } int rv = PyDict_DelItem(self->vtk_dict, attr); if (rv < 0) { PyErr_SetString(PyExc_AttributeError, "delete non-existing class attribute"); } return rv; } } //-------------------------------------------------------------------- static PyObject *PyVTKObject_PyGetAttr(PyVTKObject *self, PyObject *attr) { char *name = PyString_AsString(attr); PyVTKClass *pyclass = self->vtk_class; PyObject *bases; PyObject *value; if ((value = PyDict_GetItem(self->vtk_dict, attr))) { Py_INCREF(value); return value; } if (name[0] == '_') { if (strcmp(name,"__class__") == 0) { Py_INCREF(self->vtk_class); return (PyObject *)self->vtk_class; } if (strcmp(name,"__this__") == 0) { char buf[256]; sprintf(buf,"p_%s", self->vtk_ptr->GetClassName()); return PyString_FromString(vtkPythonManglePointer(self->vtk_ptr,buf)); } if (strcmp(name,"__doc__") == 0) { Py_INCREF(pyclass->vtk_doc); return pyclass->vtk_doc; } if (strcmp(name,"__dict__") == 0) { Py_INCREF(self->vtk_dict); return self->vtk_dict; } /* __methods__ is no longer applicable, methods are in __dict__ if (strcmp(name,"__methods__") == 0) { PyMethodDef *meth = pyclass->vtk_methods; PyObject *lst; int i, n, m; n = 0; if ((lst = PyList_New(0)) == NULL) { return NULL; } bases = NULL; while (pyclass != NULL) { m = 0; for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++) { for (i = 0; i < n; i++) { if (strcmp(PyString_AsString(PyList_GetItem(lst,i)), meth->ml_name) == 0) { break; } } if (i == n && PyDict_GetItemString(self->vtk_dict, meth->ml_name) == 0) { if (PyList_Append(lst,PyString_FromString(meth->ml_name)) == -1) { Py_DECREF(lst); return NULL; } m++; } } n += m; bases = pyclass->vtk_bases; pyclass = NULL; if (PyTuple_Size(bases)) { pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0); } } PyList_Sort(lst); return lst; } if (strcmp(name,"__members__") == 0) { PyObject *lst; if ((lst = PyList_New(6)) != NULL) { PyList_SetItem(lst,0,PyString_FromString("__class__")); PyList_SetItem(lst,1,PyString_FromString("__dict__")); PyList_SetItem(lst,2,PyString_FromString("__doc__")); PyList_SetItem(lst,3,PyString_FromString("__members__")); PyList_SetItem(lst,4,PyString_FromString("__methods__")); PyList_SetItem(lst,5,PyString_FromString("__this__")); } return lst; } */ } while (pyclass != NULL) { PyMethodDef *meth; if (pyclass->vtk_dict == NULL) { pyclass->vtk_dict = PyDict_New(); for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++) { PyDict_SetItemString(pyclass->vtk_dict,meth->ml_name, PyCFunction_New(meth, (PyObject *)pyclass)); } } value = PyDict_GetItem(pyclass->vtk_dict, attr); if (value) { if (PyCFunction_Check(value)) { return PyCFunction_New(((PyCFunctionObject *)value)->m_ml, (PyObject *)self); } else if (PyCallable_Check(value)) { return PyMethod_New(value, (PyObject *)self, (PyObject *)self->vtk_class); } Py_INCREF(value); return value; } bases = ((PyVTKClass *)pyclass)->vtk_bases; pyclass = NULL; if (PyTuple_Size(bases)) { pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0); } } // try the __getattr__ attribute if set pyclass = self->vtk_class; if (pyclass->vtk_getattr) { PyObject *args = Py_BuildValue((char*)"(OO)", self, attr); PyObject *res = PyEval_CallObject(pyclass->vtk_getattr, args); Py_DECREF(args); return res; } PyErr_SetString(PyExc_AttributeError, name); return NULL; } //-------------------------------------------------------------------- class vtkPythonDeleteCommand : public vtkCommand { public: static vtkPythonDeleteCommand *New(PyVTKObject *obj) { return new vtkPythonDeleteCommand(obj); }; void Execute(vtkObject *caller, unsigned long, void *); private: vtkPythonDeleteCommand(PyVTKObject *obj) : Self(obj) {}; PyVTKObject *Self; }; void vtkPythonDeleteCommand::Execute(vtkObject *caller, unsigned long vtkNotUsed(id), void *vtkNotUsed(data)) { if (this->Self->vtk_ptr != caller) { vtkGenericWarningMacro("Python vs. VTK mismatch for " << caller); return; } #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_STATE state = PyGILState_Ensure(); #endif vtkPythonDeleteObjectFromHash((PyObject *)this->Self); Py_DECREF((PyObject *)this->Self->vtk_class); Py_DECREF(this->Self->vtk_dict); #if (PY_MAJOR_VERSION >= 2) PyObject_Del(this->Self); #else PyMem_DEL(this->Self); #endif #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_Release(state); #endif } //-------------------------------------------------------------------- static void PyVTKObject_PyDelete(PyVTKObject *self) { #if PY_VERSION_HEX >= 0x02010000 if (self->vtk_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); } #endif self->vtk_ptr->Delete(); // the rest of the delection is handled when the VTK-level object // is destroyed vtkPythonDeleteObjectFromHash((PyObject *)self); Py_DECREF((PyObject *)self->vtk_class); Py_DECREF(self->vtk_dict); #if (PY_MAJOR_VERSION >= 2) PyObject_Del(self); #else PyMem_DEL(self); #endif } //-------------------------------------------------------------------- static PyTypeObject PyVTKObjectType = { PyObject_HEAD_INIT(&PyType_Type) 0, (char*)"vtkobject", // tp_name sizeof(PyVTKObject), // tp_basicsize 0, // tp_itemsize (destructor)PyVTKObject_PyDelete, // tp_dealloc (printfunc)0, // tp_print (getattrfunc)0, // tp_getattr (setattrfunc)0, // tp_setattr (cmpfunc)0, // tp_compare (reprfunc)PyVTKObject_PyRepr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping (hashfunc)0, // tp_hash (ternaryfunc)0, // tp_call (reprfunc)PyVTKObject_PyString, // tp_string (getattrofunc)PyVTKObject_PyGetAttr, // tp_getattro (setattrofunc)PyVTKObject_PySetAttr, // tp_setattro 0, // tp_as_buffer #if PY_VERSION_HEX >= 0x02010000 Py_TPFLAGS_HAVE_WEAKREFS, // tp_flags #else 0, // tp_flags #endif (char*)"A VTK object. Special attributes are: __class__ (the class that this object belongs to), __dict__ (user-controlled attributes), __doc__ (the docstring for the class), __methods__ (a list of all methods for this object), and __this__ (a string that contains the hexidecimal address of the underlying VTK object)", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare #if PY_VERSION_HEX >= 0x02010000 offsetof(PyVTKObject, vtk_weakreflist),// tp_weaklistoffset #else 0, // tp_weaklistoffset #endif VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED }; int PyVTKObject_Check(PyObject *obj) { return (obj->ob_type == &PyVTKObjectType); } PyObject *PyVTKObject_New(PyObject *pyvtkclass, vtkObjectBase *ptr) { PyVTKClass *vtkclass = (PyVTKClass *)pyvtkclass; if (ptr) { ptr->Register(NULL); } else if (vtkclass->vtk_new != NULL) { ptr = vtkclass->vtk_new(); } else { PyErr_SetString(PyExc_TypeError, (char*)"this is an abstract class and cannot be instantiated"); return 0; } #if (PY_MAJOR_VERSION >= 2) PyVTKObject *self = PyObject_New(PyVTKObject, &PyVTKObjectType); #else PyVTKObject *self = PyObject_NEW(PyVTKObject, &PyVTKObjectType); #endif self->vtk_ptr = ptr; PyObject *cls = NULL; vtkstd::map::iterator i = vtkPythonHash->ClassHash->find(ptr->GetClassName()); if(i != vtkPythonHash->ClassHash->end()) { cls = i->second; } self->vtk_class = (PyVTKClass *)cls; // If the class was not in the dictionary (i.e. if there is no 'python' // level class to support the VTK level class) we fall back to this. if (self->vtk_class == NULL || vtkclass->vtk_methods == NULL) { self->vtk_class = vtkclass; } Py_INCREF(self->vtk_class); self->vtk_dict = PyDict_New(); #if PY_VERSION_HEX >= 0x02010000 self->vtk_weakreflist = NULL; #endif vtkPythonAddObjectToHash((PyObject *)self, ptr); /* I'll reinstate this later ptr->AddObserver(vtkCommand::DeleteEvent, vtkPythonDeleteCommand::New(self)); */ return (PyObject *)self; } //-------------------------------------------------------------------- static PyObject *PyVTKClass_PyString(PyVTKClass *self) { char buf[255]; sprintf(buf,"%s.%s", PyString_AsString(self->vtk_module), PyString_AsString(self->vtk_name)); return PyString_FromString(buf); } //-------------------------------------------------------------------- static PyObject *PyVTKClass_PyRepr(PyVTKClass *self) { char buf[255]; sprintf(buf,"<%s %s.%s at %p>",self->ob_type->tp_name, PyString_AsString(self->vtk_module), PyString_AsString(self->vtk_name), self); return PyString_FromString(buf); } //-------------------------------------------------------------------- static PyObject *PyVTKClass_PyCall(PyVTKClass *self, PyObject *arg, PyObject *kw) { static PyObject *initstr = 0; if (((PyVTKClass *)self)->vtk_dict) { if (initstr == 0) { initstr = PyString_FromString("__init__"); } PyObject *initfunc; initfunc = PyDict_GetItem(self->vtk_dict, initstr); if (initfunc) { PyObject *obj = PyVTKObject_New((PyObject *)self,NULL); PyObject *cinitfunc = PyVTKObject_PyGetAttr((PyVTKObject *)obj, initstr); PyObject *res = PyEval_CallObjectWithKeywords(cinitfunc, arg, kw); if (res == NULL) { Py_DECREF(obj); obj = NULL; } else if (res != Py_None) { PyErr_SetString(PyExc_TypeError, "__init__() should return None"); Py_DECREF(obj); obj = NULL; } Py_DECREF(cinitfunc); return obj; } } if (kw != NULL) { PyErr_SetString(PyExc_TypeError, "this function takes no keyword arguments"); return NULL; } if (PyArg_ParseTuple(arg,(char*)"")) { return PyVTKObject_New((PyObject *)self, NULL); } PyErr_Clear(); if (PyArg_ParseTuple(arg,(char*)"O", &arg)) { return vtkPythonGetObjectFromObject(arg, PyString_AsString(self->vtk_name)); } PyErr_Clear(); PyErr_SetString(PyExc_TypeError, "function requires 0 or 1 arguments"); return NULL; } //-------------------------------------------------------------------- static PyObject *PyVTKClass_PyGetAttr(PyVTKClass *self, PyObject *attr) { char *name = PyString_AsString(attr); PyVTKClass *pyclass = self; PyObject *bases; while (pyclass != NULL) { PyMethodDef *meth; PyObject *value; if (pyclass->vtk_dict == NULL) { pyclass->vtk_dict = PyDict_New(); for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++) { PyDict_SetItemString(pyclass->vtk_dict,meth->ml_name, PyCFunction_New(meth, (PyObject *)pyclass)); } } value = PyDict_GetItem(pyclass->vtk_dict, attr); if (value) { Py_INCREF(value); return value; } bases = pyclass->vtk_bases; pyclass = NULL; if (PyTuple_Size(bases)) { pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0); } } if (name[0] == '_') { pyclass = (PyVTKClass *)self; if (strcmp(name,"__bases__") == 0) { Py_INCREF(pyclass->vtk_bases); return pyclass->vtk_bases; } if (strcmp(name,"__name__") == 0) { Py_INCREF(pyclass->vtk_name); return pyclass->vtk_name; } if (strcmp(name,"__module__") == 0) { Py_INCREF(pyclass->vtk_module); return pyclass->vtk_module; } if (strcmp(name,"__dict__") == 0 && pyclass->vtk_dict) { Py_INCREF(pyclass->vtk_dict); return pyclass->vtk_dict; } if (strcmp(name,"__doc__") == 0) { Py_INCREF(pyclass->vtk_doc); return pyclass->vtk_doc; } /* methods are stored in __dict__, so this is irrelevant if (strcmp(name,"__methods__") == 0) { PyMethodDef *meth = pyclass->vtk_methods; PyObject *lst; int i, n; for (n = 0; meth && meth[n].ml_name; n++); if ((lst = PyList_New(0)) != NULL) { meth = pyclass->vtk_methods; for (i = 0; i < n; i++) { if (pyclass->vtk_dict == NULL || PyDict_GetItemString(pyclass->vtk_dict, meth[i].ml_name) == 0) { PyList_Append(lst, PyString_FromString(meth[i].ml_name)); } } PyList_Sort(lst); } return lst; } if (strcmp(name,"__members__") == 0) { int n = 6; int i = 0; PyObject *lst; if (pyclass->vtk_dict) { n++; } if ((lst = PyList_New(n)) != NULL) { PyList_SetItem(lst,i++,PyString_FromString("__bases__")); if (pyclass->vtk_dict) { PyList_SetItem(lst,i++,PyString_FromString("__dict__")); } PyList_SetItem(lst,i++,PyString_FromString("__doc__")); PyList_SetItem(lst,i++,PyString_FromString("__members__")); PyList_SetItem(lst,i++,PyString_FromString("__methods__")); PyList_SetItem(lst,i++,PyString_FromString("__module__")); PyList_SetItem(lst,i++,PyString_FromString("__name__")); } return lst; } */ } PyErr_SetString(PyExc_AttributeError, name); return NULL; } //-------------------------------------------------------------------- static void PyVTKClass_PyDelete(PyVTKClass *self) { Py_XDECREF(self->vtk_bases); Py_XDECREF(self->vtk_dict); Py_XDECREF(self->vtk_name); Py_XDECREF(self->vtk_getattr); Py_XDECREF(self->vtk_setattr); Py_XDECREF(self->vtk_delattr); Py_XDECREF(self->vtk_module); Py_XDECREF(self->vtk_doc); #if (PY_MAJOR_VERSION >= 2) PyObject_Del(self); #else PyMem_DEL(self); #endif } //-------------------------------------------------------------------- static PyObject *PyVTKClassMetaType_GetAttr(PyTypeObject *t, char *name) { if (strcmp(name, "__name__") == 0) { return PyString_FromString(t->tp_name); } if (strcmp(name, "__doc__") == 0) { const char *doc = t->tp_doc; if (doc != NULL) { return PyString_FromString(doc); } Py_INCREF(Py_None); return Py_None; } if (strcmp(name, "__members__") == 0) { return Py_BuildValue((char*)"[ss]", "__doc__", "__name__"); } PyErr_SetString(PyExc_AttributeError, name); return NULL; } //-------------------------------------------------------------------- static PyObject *PyVTKClassMetaType_Repr(PyTypeObject *v) { char buf[100]; sprintf(buf, "", v->tp_name); return PyString_FromString(buf); } //-------------------------------------------------------------------- static PyObject *PyVTKClass_NewSubclass(PyObject *self, PyObject *args, PyObject *kw); //-------------------------------------------------------------------- PyTypeObject PyVTKClassMetaType = { PyObject_HEAD_INIT(&PyType_Type) 0, /* Number of items for varobject */ (char*)"vtkclass type", /* Name of this type */ sizeof(PyTypeObject), /* Basic object size */ 0, /* Item size for varobject */ 0, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)PyVTKClassMetaType_GetAttr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ (reprfunc)PyVTKClassMetaType_Repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ (ternaryfunc)PyVTKClass_NewSubclass, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_xxx1*/ 0, /*tp_xxx2*/ 0, /*tp_xxx3*/ 0, /*tp_xxx4*/ (char*)"Define the behavior of a particular type of object.", 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED }; //-------------------------------------------------------------------- static PyTypeObject PyVTKClassType = { PyObject_HEAD_INIT(&PyVTKClassMetaType) 0, (char*)"vtkclass", // tp_name sizeof(PyVTKClass), // tp_basicsize 0, // tp_itemsize (destructor)PyVTKClass_PyDelete, // tp_dealloc (printfunc)0, // tp_print (getattrfunc)0, // tp_getattr (setattrfunc)0, // tp_setattr (cmpfunc)0, // tp_compare (reprfunc)PyVTKClass_PyRepr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping (hashfunc)0, // tp_hash (ternaryfunc)PyVTKClass_PyCall, // tp_call (reprfunc)PyVTKClass_PyString, // tp_string (getattrofunc)PyVTKClass_PyGetAttr, // tp_getattro (setattrofunc)0, // tp_setattro 0, // tp_as_buffer 0, // tp_flags (char*)"A generator for VTK objects. Special attributes are: __bases__ (a tuple of base classes), __dict__ (user-defined methods and attributes), __doc__ (the docstring for the class), __name__ (the name of class), __methods__ (methods for this class, not including inherited methods or user-defined methods), and __module__ (module that the class is defined in).", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED }; int PyVTKClass_Check(PyObject *obj) { return (obj->ob_type == &PyVTKClassType); } //-------------------------------------------------------------------- // Concatenate an array of strings into a single string. The resulting // string is allocated via new. The array of strings must be null-terminated, // e.g. static char *strings[] = {"string1", "string2", NULL}; static PyObject *vtkBuildDocString(char *docstring[]) { PyObject *result; char *data; int i, j, n; int *m; int total = 0; for (n = 0; docstring[n] != NULL; n++); m = new int[n]; for (i = 0; i < n; i++) { m[i] = static_cast(strlen(docstring[i])); total += m[i]; } result = PyString_FromStringAndSize(docstring[0], m[0]); if (n > 1) { _PyString_Resize(&result, total); } data = PyString_AsString(result); j = m[0]; for (i = 1; i < n; i++) { strcpy(&data[j], docstring[i]); j += m[i]; } delete [] m; return result; } PyObject *PyVTKClass_New(vtknewfunc constructor, PyMethodDef *methods, char *classname, char *modulename, char *docstring[], PyObject *base) { static PyObject *modulestr[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static int nmodulestr = 10; PyObject *moduleobj = 0; PyObject *self = NULL; int i; if (vtkPythonHash) { vtkstd::map::iterator it = vtkPythonHash->ClassHash->find(classname); if(it != vtkPythonHash->ClassHash->end()) { self = it->second; } } if (self) { Py_INCREF(self); } else { #if (PY_MAJOR_VERSION >= 2) PyVTKClass *class_self = PyObject_New(PyVTKClass, &PyVTKClassType); #else PyVTKClass *class_self = PyObject_NEW(PyVTKClass, &PyVTKClassType); #endif self = (PyObject *)class_self; if (base) { class_self->vtk_bases = PyTuple_New(1); PyTuple_SET_ITEM(class_self->vtk_bases, 0, base); } else { class_self->vtk_bases = PyTuple_New(0); } class_self->vtk_dict = NULL; class_self->vtk_name = PyString_FromString(classname); class_self->vtk_getattr = NULL; class_self->vtk_setattr = NULL; class_self->vtk_delattr = NULL; class_self->vtk_methods = methods; class_self->vtk_new = constructor; class_self->vtk_doc = vtkBuildDocString(docstring); // intern the module string for (i = 0; i < nmodulestr; i++) { if (modulestr[i] == 0) { modulestr[i] = PyString_InternFromString(modulename); moduleobj = modulestr[i]; Py_INCREF(moduleobj); break; } else if (strcmp(modulename,PyString_AsString(modulestr[i])) == 0) { moduleobj = modulestr[i]; Py_INCREF(moduleobj); break; } } if (i == nmodulestr) { moduleobj = PyString_FromString(modulename); } class_self->vtk_module = moduleobj; vtkPythonAddClassToHash(self,classname); } return (PyObject *)self; } //-------------------------------------------------------------------- static PyObject *PyVTKClass_NewSubclass(PyObject *, PyObject *args, PyObject *kw) { static const char *kwlist[] = {"name", "bases", "dict", NULL}; PyVTKClass *newclass; char *classname; PyObject *globals; PyObject *bases; PyVTKClass *base; PyObject *attributes; if ((PyArg_ParseTupleAndKeywords(args, kw, (char*)"sOO", (char**)kwlist, &classname, &bases, &attributes))) { if (!PyTuple_Check(bases) || PyTuple_Size(bases) != 1) { PyErr_SetString(PyExc_ValueError, "multiple inheritence is not allowed with VTK classes"); return NULL; } base = (PyVTKClass *)PyTuple_GetItem(bases,0); if (base == 0) { PyErr_SetString(PyExc_ValueError,"bases must be a tuple"); return NULL; } if (!PyVTKClass_Check((PyObject *)base)) { PyErr_SetString(PyExc_ValueError,"base class is not a VTK class"); return NULL; } if (!PyDict_Check(attributes)) { PyErr_SetString(PyExc_ValueError,"namespace not provided"); return NULL; } if (PyDict_GetItemString(attributes, (char*)"__del__")) { PyErr_SetString(PyExc_ValueError, "__del__ attribute is not supported"); return NULL; } #if (PY_MAJOR_VERSION >= 2) newclass = PyObject_New(PyVTKClass, &PyVTKClassType); #else newclass = PyObject_NEW(PyVTKClass, &PyVTKClassType); #endif Py_INCREF(bases); Py_INCREF(attributes); newclass->vtk_bases = bases; newclass->vtk_dict = attributes; newclass->vtk_name = PyString_FromString(classname); newclass->vtk_getattr = PyDict_GetItemString(attributes, (char*)"__getattr__"); if (newclass->vtk_getattr == 0) { newclass->vtk_getattr = base->vtk_getattr; } Py_XINCREF(newclass->vtk_getattr); newclass->vtk_setattr = PyDict_GetItemString(attributes, (char*)"__setattr__"); if (newclass->vtk_setattr == 0) { newclass->vtk_setattr = base->vtk_setattr; } Py_XINCREF(newclass->vtk_setattr); newclass->vtk_delattr = PyDict_GetItemString(attributes, (char*)"__delattr__"); if (newclass->vtk_delattr == 0) { newclass->vtk_delattr = base->vtk_delattr; } Py_XINCREF(newclass->vtk_delattr); newclass->vtk_methods = NULL; newclass->vtk_new = base->vtk_new; newclass->vtk_module = NULL; newclass->vtk_doc = NULL; globals = PyEval_GetGlobals(); if (globals != NULL) { PyObject *modname = PyDict_GetItemString(globals, (char*)"__name__"); if (modname != NULL) { Py_INCREF(modname); newclass->vtk_module = modname; } } if (newclass->vtk_module == NULL) { newclass->vtk_module = PyString_FromString("__main__"); } newclass->vtk_doc = PyDict_GetItemString(attributes, (char*)"__doc__"); if (newclass->vtk_doc) { Py_INCREF(newclass->vtk_doc); PyDict_DelItemString(attributes, (char*)"__doc__"); } else { newclass->vtk_doc = PyString_FromString(""); } return (PyObject *)newclass; } return NULL; } //-------------------------------------------------------------------- static PyObject *PyVTKSpecialObject_PyString(PyVTKSpecialObject *self) { Py_INCREF(self->vtk_name); return self->vtk_name; } //-------------------------------------------------------------------- static PyObject *PyVTKSpecialObject_PyRepr(PyVTKSpecialObject *self) { char buf[255]; sprintf(buf,"<%s %s at %p>", self->ob_type->tp_name, PyString_AsString(self->vtk_name), self); return PyString_FromString(buf); } //-------------------------------------------------------------------- static PyObject *PyVTKSpecialObject_PyGetAttr(PyVTKSpecialObject *self, PyObject *attr) { char *name = PyString_AsString(attr); PyMethodDef *meth; if (name[0] == '_') { if (strcmp(name,"__name__") == 0) { Py_INCREF(self->vtk_name); return self->vtk_name; } if (strcmp(name,"__doc__") == 0) { Py_INCREF(self->vtk_doc); return self->vtk_doc; } if (strcmp(name,"__methods__") == 0) { meth = self->vtk_methods; PyObject *lst; int i, n; for (n = 0; meth && meth[n].ml_name; n++); if ((lst = PyList_New(n)) != NULL) { meth = self->vtk_methods; for (i = 0; i < n; i++) { PyList_SetItem(lst, i, PyString_FromString(meth[i].ml_name)); } PyList_Sort(lst); } return lst; } if (strcmp(name,"__members__") == 0) { PyObject *lst; if ((lst = PyList_New(4)) != NULL) { PyList_SetItem(lst,0,PyString_FromString("__doc__")); PyList_SetItem(lst,1,PyString_FromString("__members__")); PyList_SetItem(lst,2,PyString_FromString("__methods__")); PyList_SetItem(lst,3,PyString_FromString("__name__")); } return lst; } } for (meth = self->vtk_methods; meth && meth->ml_name; meth++) { if (name[0] == meth->ml_name[0] && strcmp(name+1, meth->ml_name+1) == 0) { return PyCFunction_New(meth, (PyObject *)self); } } PyErr_SetString(PyExc_AttributeError, name); return NULL; } //-------------------------------------------------------------------- static void PyVTKSpecialObject_PyDelete(PyVTKSpecialObject *self) { self->vtk_ptr = NULL; Py_XDECREF(self->vtk_name); Py_XDECREF(self->vtk_doc); #if (PY_MAJOR_VERSION >= 2) PyObject_Del(self); #else PyMem_DEL(self); #endif } //-------------------------------------------------------------------- static PyTypeObject PyVTKSpecialObjectType = { PyObject_HEAD_INIT(&PyType_Type) 0, (char*)"vtkspecialobject", // tp_name sizeof(PyVTKSpecialObject), // tp_basicsize 0, // tp_itemsize (destructor)PyVTKSpecialObject_PyDelete, // tp_dealloc (printfunc)0, // tp_print (getattrfunc)0, // tp_getattr (setattrfunc)0, // tp_setattr (cmpfunc)0, // tp_compare (reprfunc)PyVTKSpecialObject_PyRepr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping (hashfunc)0, // tp_hash (ternaryfunc)0, // tp_call (reprfunc)PyVTKSpecialObject_PyString, // tp_string (getattrofunc)PyVTKSpecialObject_PyGetAttr, // tp_getattro (setattrofunc)0, // tp_setattro 0, // tp_as_buffer 0, // tp_flags (char*)"vtkspecialobject - a vtk object not derived from vtkObjectBase.", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED }; int PyVTKSpecialObject_Check(PyObject *obj) { return (obj->ob_type == &PyVTKSpecialObjectType); } PyObject *PyVTKSpecialObject_New(void *ptr, PyMethodDef *methods, char *classname, char *docstring[]) { #if (PY_MAJOR_VERSION >= 2) PyVTKSpecialObject *self = PyObject_New(PyVTKSpecialObject, &PyVTKSpecialObjectType); #else PyVTKSpecialObject *self = PyObject_NEW(PyVTKSpecialObject, &PyVTKSpecialObjectType); #endif self->vtk_ptr = ptr; self->vtk_methods = methods; self->vtk_name = PyString_FromString(classname); self->vtk_doc = vtkBuildDocString(docstring); return (PyObject *)self; } //-------------------------------------------------------------------- vtkObjectBase *PyArg_VTKParseTuple(PyObject *pself, PyObject *args, char *format, ...) { PyVTKObject *self = (PyVTKObject *)pself; vtkObjectBase *obj = NULL; va_list va; va_start(va, format); /* check if this was called as an unbound method */ if (self->ob_type == &PyVTKClassType) { int n = PyTuple_Size(args); PyVTKClass *vtkclass = (PyVTKClass *)self; if (n == 0 || (self = (PyVTKObject *)PyTuple_GetItem(args, 0)) == NULL || self->ob_type != &PyVTKObjectType || !self->vtk_ptr->IsA(PyString_AsString(vtkclass->vtk_name))) { char buf[256]; sprintf(buf,"unbound method requires a %s as the first argument", PyString_AsString(vtkclass->vtk_name)); PyErr_SetString(PyExc_ValueError,buf); return NULL; } // re-slice the args to remove 'self' args = PyTuple_GetSlice(args,1,n); if (PyArg_VaParse(args,format,va)) { obj = self->vtk_ptr; } Py_DECREF(args); } /* it was called as a bound method */ else { if (PyArg_VaParse(args,format,va)) { obj = self->vtk_ptr; } } return obj; } //-------------------------------------------------------------------- void vtkPythonAddClassToHash(PyObject *vtkclass, const char *classname) { if (vtkPythonHash == NULL) { vtkPythonHash = new vtkPythonUtil(); Py_AtExit(vtkPythonHashDelete); } #ifdef VTKPYTHONDEBUG // vtkGenericWarningMacro("Adding an type " << type << " to hash ptr"); #endif // lets make sure it isn't already there vtkstd::map::iterator i = vtkPythonHash->ClassHash->find(classname); if(i != vtkPythonHash->ClassHash->end()) { #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Attempt to add type to the hash when already there!!!"); #endif return; } (*vtkPythonHash->ClassHash)[classname] = vtkclass; #ifdef VTKPYTHONDEBUG // vtkGenericWarningMacro("Added type to hash type = " << typeObject); #endif } //-------------------------------------------------------------------- void vtkPythonAddObjectToHash(PyObject *obj, vtkObjectBase *ptr) { if (vtkPythonHash == NULL) { vtkPythonHash = new vtkPythonUtil(); Py_AtExit(vtkPythonHashDelete); } #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Adding an object to hash ptr = " << ptr); #endif ((PyVTKObject *)obj)->vtk_ptr = ptr; (*vtkPythonHash->ObjectHash)[ptr] = obj; #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Added object to hash obj= " << obj << " " << ptr); #endif } //-------------------------------------------------------------------- void vtkPythonDeleteObjectFromHash(PyObject *obj) { vtkObjectBase *ptr = ((PyVTKObject *)obj)->vtk_ptr; #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Deleting an object from hash obj = " << obj << " " << obj->vtk_ptr); #endif vtkPythonHash->ObjectHash->erase(ptr); } //-------------------------------------------------------------------- static PyObject *vtkFindNearestBase(vtkObjectBase *ptr); PyObject *vtkPythonGetObjectFromPointer(vtkObjectBase *ptr) { PyObject *obj = NULL; #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Checking into pointer " << ptr); #endif if (ptr) { vtkstd::map::iterator i = vtkPythonHash->ObjectHash->find(ptr); if(i != vtkPythonHash->ObjectHash->end()) { obj = i->second; } if (obj) { Py_INCREF(obj); } } else { Py_INCREF(Py_None); obj = Py_None; } #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Checking into pointer " << ptr << " obj = " << obj); #endif if (obj == NULL) { PyObject *vtkclass = NULL; vtkstd::map::iterator i = vtkPythonHash->ClassHash->find(ptr->GetClassName()); if(i != vtkPythonHash->ClassHash->end()) { vtkclass = i->second; } // if the class was not in the hash, then find the nearest base class // that is and associate ptr->GetClassName() with that base class if (vtkclass == NULL) { vtkclass = vtkFindNearestBase(ptr); vtkPythonAddClassToHash(vtkclass, ptr->GetClassName()); } obj = PyVTKObject_New(vtkclass, ptr); } return obj; } // this is a helper function to find the nearest base class for an // object whose class is not in the ClassDict static PyObject *vtkFindNearestBase(vtkObjectBase *ptr) { PyObject *nearestbase = NULL; int maxdepth = 0; int depth; for(vtkstd::map::iterator classes = vtkPythonHash->ClassHash->begin(); classes != vtkPythonHash->ClassHash->end(); ++classes) { PyObject *pyclass = classes->second; if (ptr->IsA(PyString_AsString(((PyVTKClass *)pyclass)->vtk_name))) { PyObject *cls = pyclass; PyObject *bases = ((PyVTKClass *)pyclass)->vtk_bases; // count the heirarchy depth for this class for (depth = 0; PyTuple_Size(bases) != 0; depth++) { cls = PyTuple_GetItem(bases,0); bases = ((PyVTKClass *)cls)->vtk_bases; } // we want the class that is furthest from vtkObjectBase if (depth > maxdepth) { maxdepth = depth; nearestbase = pyclass; } } } return nearestbase; } //-------------------------------------------------------------------- vtkObjectBase *vtkPythonGetPointerFromObject(PyObject *obj, const char *result_type) { vtkObjectBase *ptr; // convert Py_None to NULL every time if (obj == Py_None) { return NULL; } // check to ensure it is a vtk object if (obj->ob_type != &PyVTKObjectType) { obj = PyObject_GetAttrString(obj,(char*)"__vtk__"); if (obj) { PyObject *arglist = Py_BuildValue((char*)"()"); PyObject *result = PyEval_CallObject(obj, arglist); Py_DECREF(arglist); Py_DECREF(obj); if (result == NULL) { return NULL; } if (result->ob_type != &PyVTKObjectType) { PyErr_SetString(PyExc_ValueError,"__vtk__() doesn't return a VTK object"); Py_DECREF(result); return NULL; } else { ptr = ((PyVTKObject *)result)->vtk_ptr; Py_DECREF(result); } } else { #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Object " << obj << " is not a VTK object!!"); #endif PyErr_SetString(PyExc_ValueError,"method requires a VTK object"); return NULL; } } else { ptr = ((PyVTKObject *)obj)->vtk_ptr; } #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Checking into obj " << obj << " ptr = " << ptr); #endif if (ptr->IsA(result_type)) { #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("Got obj= " << obj << " ptr= " << ptr << " " << result_type); #endif return ptr; } else { char error_string[256]; #ifdef VTKPYTHONDEBUG vtkGenericWarningMacro("vtk bad argument, type conversion failed."); #endif sprintf(error_string,"method requires a %s, a %s was provided.", result_type,((vtkObjectBase *)ptr)->GetClassName()); PyErr_SetString(PyExc_ValueError,error_string); return NULL; } } PyObject *vtkPythonGetObjectFromObject(PyObject *arg, const char *type) { if (PyString_Check(arg)) { char *ptrText = PyString_AsString(arg); vtkObjectBase *ptr; char typeCheck[256]; // typeCheck is currently not used int i = sscanf(ptrText,"_%lx_%s",(long *)&ptr,typeCheck); if (i <= 0) { i = sscanf(ptrText,"Addr=0x%lx",(long *)&ptr); } if (i <= 0) { i = sscanf(ptrText,"%lx",(long *)&ptr); } if (i <= 0) { PyErr_SetString(PyExc_ValueError,"could not extract hexidecimal address from argument string"); return NULL; } if (!ptr->IsA(type)) { char error_string[256]; sprintf(error_string,"method requires a %s address, a %s address was provided.", type,((vtkObjectBase *)ptr)->GetClassName()); PyErr_SetString(PyExc_TypeError,error_string); return NULL; } return vtkPythonGetObjectFromPointer(ptr); } PyErr_SetString(PyExc_TypeError,"method requires a string argument"); return NULL; } //-------------------------------------------------------------------- // mangle a void pointer into a SWIG-style string char *vtkPythonManglePointer(void *ptr, const char *type) { static char ptrText[128]; sprintf(ptrText,"_%*.*lx_%s",2*(int)sizeof(void *),2*(int)sizeof(void *), vtkConvertPtrToLong(ptr),type); return ptrText; } //-------------------------------------------------------------------- // unmangle a void pointer from a SWIG-style string void *vtkPythonUnmanglePointer(char *ptrText, int *len, const char *type) { int i; void *ptr; char typeCheck[128]; if (*len < 128) { i = sscanf(ptrText,"_%lx_%s",(long *)&ptr,typeCheck); if (strcmp(type,typeCheck) == 0) { // sucessfully unmangle *len = 0; return ptr; } else if (i == 2) { // mangled pointer of wrong type *len = -1; return NULL; } } // couldn't unmangle: return string as void pointer if it didn't look // like a SWIG mangled pointer return (void *)ptrText; } //-------------------------------------------------------------------- // These functions check an array that was sent to a method to see if // any of the values were changed by the method. // If a value was changed, then the corresponding value in the python // list is modified. template static inline int vtkPythonCheckFloatArray(PyObject *args, int i, T *a, int n) { int changed = 0; PyObject *seq = PyTuple_GET_ITEM(args, i); for (i = 0; i < n; i++) { PyObject *oldobj = PySequence_GetItem(seq, i); T oldval = (T)PyFloat_AsDouble(oldobj); Py_DECREF(oldobj); changed |= (a[i] != oldval); } if (changed) { for (i = 0; i < n; i++) { PyObject *newobj = PyFloat_FromDouble(a[i]); int rval = PySequence_SetItem(seq, i, newobj); Py_DECREF(newobj); if (rval == -1) { return -1; } } } return 0; } template static inline int vtkPythonCheckIntArray(PyObject *args, int i, T *a, int n) { int changed = 0; PyObject *seq = PyTuple_GET_ITEM(args, i); for (i = 0; i < n; i++) { PyObject *oldobj = PySequence_GetItem(seq, i); T oldval = (T)PyInt_AsLong(oldobj); Py_DECREF(oldobj); changed |= (a[i] != oldval); } if (changed) { for (i = 0; i < n; i++) { PyObject *newobj = PyInt_FromLong(a[i]); int rval = PySequence_SetItem(seq, i, newobj); Py_DECREF(newobj); if (rval == -1) { return -1; } } } return 0; } #if defined(VTK_TYPE_USE_LONG_LONG) || defined(VTK_TYPE_USE___INT64) template static inline int vtkPythonCheckLongArray(PyObject *args, int i, T *a, int n) { int changed = 0; PyObject *seq = PyTuple_GET_ITEM(args, i); for (i = 0; i < n; i++) { PyObject *oldobj = PySequence_GetItem(seq, i); T oldval; if (PyLong_Check(oldobj)) { #ifdef PY_LONG_LONG oldval = PyLong_AsLongLong(oldobj); #else oldval = PyLong_AsLong(oldobj); #endif } else { oldval = PyInt_AsLong(oldobj); } Py_DECREF(oldobj); changed |= (a[i] != oldval); } if (changed) { for (i = 0; i < n; i++) { #if defined(VTK_TYPE_USE_LONG_LONG) # if defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF_LONG_LONG) PyObject *newobj = PyLong_FromLongLong(a[i]); # else PyObject *newobj = PyInt_FromLong((long)a[i]); # endif #else # if defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF___INT64) PyObject *newobj = PyLong_FromLongLong(a[i]); # else PyObject *newobj = PyInt_FromLong((long)a[i]); # endif #endif int rval = PySequence_SetItem(seq, i, newobj); Py_DECREF(newobj); if (rval == -1) { return -1; } } } return 0; } #endif int vtkPythonCheckArray(PyObject *args, int i, char *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, signed char *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, unsigned char *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, short *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, unsigned short *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, int *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, unsigned int *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, long *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, unsigned long *a, int n) { return vtkPythonCheckIntArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, float *a, int n) { return vtkPythonCheckFloatArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, double *a, int n) { return vtkPythonCheckFloatArray(args, i, a, n); } #if defined(VTK_TYPE_USE_LONG_LONG) int vtkPythonCheckArray(PyObject *args, int i, long long *a, int n) { return vtkPythonCheckLongArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, unsigned long long *a, int n) { return vtkPythonCheckLongArray(args, i, a, n); } #endif #if defined(VTK_TYPE_USE___INT64) int vtkPythonCheckArray(PyObject *args, int i, __int64 *a, int n) { return vtkPythonCheckLongArray(args, i, a, n); } int vtkPythonCheckArray(PyObject *args, int i, unsigned __int64 *a, int n) { return vtkPythonCheckLongArray(args, i, a, n); } #endif //-------------------------------------------------------------------- void vtkPythonVoidFunc(void *arg) { PyObject *arglist, *result; PyObject *func = (PyObject *)arg; #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_STATE state = PyGILState_Ensure(); #endif arglist = Py_BuildValue((char*)"()"); result = PyEval_CallObject(func, arglist); Py_DECREF(arglist); if (result) { Py_XDECREF(result); } else { if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { cerr << "Caught a Ctrl-C within python, exiting program.\n"; Py_Exit(1); } PyErr_Print(); } #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_Release(state); #endif } //-------------------------------------------------------------------- void vtkPythonVoidFuncArgDelete(void *arg) { PyObject *func = (PyObject *)arg; #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_STATE state = PyGILState_Ensure(); #endif if (func) { Py_DECREF(func); } #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_Release(state); #endif } //-------------------------------------------------------------------- vtkPythonCommand::vtkPythonCommand() { this->obj = NULL; } vtkPythonCommand::~vtkPythonCommand() { if (this->obj) { Py_DECREF(this->obj); } this->obj = NULL; } void vtkPythonCommand::SetObject(PyObject *o) { this->obj = o; } void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype, void *CallData) { PyObject *arglist, *result, *obj2; const char *eventname; #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_STATE state = PyGILState_Ensure(); #endif if (ptr && ptr->GetReferenceCount() > 0) { obj2 = vtkPythonGetObjectFromPointer(ptr); } else { Py_INCREF(Py_None); obj2 = Py_None; } eventname = this->GetStringFromEventId(eventtype); // 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) // * At the moment, only string0 is supported as that is what ErrorEvent // generates. // char CallDataTypeLiteral[] = "CallDataType"; // Need char*, not const char*. PyObject *CallDataTypeObj = PyObject_GetAttrString(this->obj, CallDataTypeLiteral); 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((char*)"(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((char*)"(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((char*)"(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((char*)"(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((char*)"(Ns)",obj2,eventname); } result = PyEval_CallObject(this->obj, arglist); Py_DECREF(arglist); if (result) { Py_DECREF(result); } else { if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { cerr << "Caught a Ctrl-C within python, exiting program.\n"; Py_Exit(1); } PyErr_Print(); } #if (PY_MAJOR_VERSION > 2) || \ ((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) PyGILState_Release(state); #endif } //--------------------------------------------------------------------