diff --git a/src/App/FeaturePythonPyImp.h b/src/App/FeaturePythonPyImp.h index 9bd0e368f..e5974773f 100644 --- a/src/App/FeaturePythonPyImp.h +++ b/src/App/FeaturePythonPyImp.h @@ -23,6 +23,8 @@ #ifndef APP_FEATUREPYTHONPYIMP_H #define APP_FEATUREPYTHONPYIMP_H +#include +#include #include #include @@ -45,6 +47,7 @@ public: /** @name callbacks and implementers for the python object methods */ //@{ + static int __setattr(PyObject *PyObj, char *attr, PyObject *value); /// callback for the addProperty() method static PyObject * staticCallback_addProperty (PyObject *self, PyObject *args); /// implementer for the addProperty() method @@ -67,6 +70,7 @@ public: int _setattr(char *attr, PyObject *value); // __setattr__ function protected: + std::map dyn_methods; private: }; diff --git a/src/App/FeaturePythonPyImp.inl b/src/App/FeaturePythonPyImp.inl index 78aa389d5..fb1d67c4e 100644 --- a/src/App/FeaturePythonPyImp.inl +++ b/src/App/FeaturePythonPyImp.inl @@ -36,7 +36,7 @@ PyTypeObject FeaturePythonPyT::Type = { FeaturePyT::PyDestructor, /*tp_dealloc*/ 0, /*tp_print*/ FeaturePyT::__getattr, /*tp_getattr*/ - FeaturePyT::__setattr, /*tp_setattr*/ + __setattr, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ @@ -219,6 +219,21 @@ FeaturePythonPyT::~FeaturePythonPyT() { } +template +int FeaturePythonPyT::__setattr(PyObject *obj, char *attr, PyObject *value) +{ + if (!static_cast(obj)->isValid()){ + PyErr_Format(PyExc_ReferenceError, "Cannot access attribute '%s' of deleted object", attr); + return -1; + } + + int ret = static_cast(obj)->_setattr(attr, value); + if (ret == 0) { + static_cast(obj)->startNotify(); + } + return ret; +} + template PyObject *FeaturePythonPyT::_getattr(char *attr) { @@ -242,6 +257,14 @@ PyObject *FeaturePythonPyT::_getattr(char *attr) } PyObject *rvalue = Py_FindMethod(Methods, this, attr); + if (rvalue == NULL) { + std::map::iterator it = dyn_methods.find(attr); + if (it != dyn_methods.end()) { + Py_INCREF(it->second); + rvalue = it->second; + PyErr_Clear(); + } + } if (rvalue == NULL) { PyErr_Clear(); return FeaturePyT::_getattr(attr); @@ -273,7 +296,31 @@ int FeaturePythonPyT::_setattr(char *attr, PyObject *value) return -1; } - return FeaturePyT::_setattr(attr, value); + int returnValue = FeaturePyT::_setattr(attr, value); + if (returnValue == -1) { + if (value) { + if (PyFunction_Check(value)) { + std::map::iterator it = dyn_methods.find(attr); + if (it != dyn_methods.end()) { + Py_XDECREF(it->second); + } + dyn_methods[attr] = PyMethod_New(value, this, 0); + returnValue = 0; + PyErr_Clear(); + } + } + else { + // delete + std::map::iterator it = dyn_methods.find(attr); + if (it != dyn_methods.end()) { + Py_XDECREF(it->second); + dyn_methods.erase(it); + returnValue = 0; + PyErr_Clear(); + } + } + } + return returnValue; } // -------------------------------------------------------------