diff --git a/Lib/python/director_h.swg b/Lib/python/director_h.swg index 361543242..485211758 100644 --- a/Lib/python/director_h.swg +++ b/Lib/python/director_h.swg @@ -24,29 +24,59 @@ /* - Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of RTTI - and dynamic_cast<>. But be aware that directors could stop working - when using this option. + Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the + native C++ RTTI and dynamic_cast<>. But be aware that directors + could stop working when using this option. */ +#ifdef SWIG_DIRECTOR_NORTTI +/* + When we don't use the native C++ RTTI, we implement a minimal one + only for Directors. +*/ +# ifndef SWIG_DIRECTOR_RTDIR +# define SWIG_DIRECTOR_RTDIR +#include +namespace Swig { + class Director; + static std::map& get_rtdir_map() { + static std::map rtdir_map; + return rtdir_map; + } + + static inline void set_rtdir(void *vptr, Director *rtdir) { + get_rtdir_map()[vptr] = rtdir; + } + + static inline Director *get_rtdir(void *vptr) { + std::map::const_iterator pos = get_rtdir_map().find(vptr); + Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0; + return rtdir; + } +} +# endif /* SWIG_DIRECTOR_RTDIR */ + +# define SWIG_DIRECTOR_CAST(Arg) Swig::get_rtdir(static_cast(Arg)) +# define SWIG_DIRECTOR_RGTR(Arg1, Arg2) Swig::set_rtdir(static_cast(Arg1), Arg2) -#if defined(SWIG_DIRECTOR_NORTTI) -# define SWIG_DIRECTOR_CAST(arg) (Swig::Director*)(arg) #else -# define SWIG_DIRECTOR_CAST(arg) dynamic_cast(arg) -#endif +# define SWIG_DIRECTOR_CAST(Arg) dynamic_cast(Arg) +# define SWIG_DIRECTOR_RGTR(Arg1, Arg2) + +#endif /* SWIG_DIRECTOR_NORTTI */ extern "C" { struct swig_type_info; } namespace Swig { + /* base class for director exceptions */ class DirectorException { protected: std::string swig_msg; public: - DirectorException(const char* /* msg */ ="") { + DirectorException(const char* msg ="") : swig_msg(msg) { } const char *getMessage() const { @@ -69,7 +99,13 @@ namespace Swig { }; /* any python exception that occurs during a director method call */ - class DirectorMethodException : public Swig::DirectorException {}; + class DirectorMethodException : public Swig::DirectorException { + public: + DirectorMethodException(const char* msg = "") + : DirectorException(msg) + { + } + }; /* attempt to call a pure virtual method via a director method */ class DirectorPureVirtualException : public Swig::DirectorException {}; diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 2614b049a..77676d716 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -71,7 +71,7 @@ Python Options (available with -python)\n\ -keyword - Use keyword arguments\n\ -classic - Use classic classes only\n\ -cppcast - Enable new C++ casting operators, useful for debugging\n\ - -nortti - Disable the use of RTTI, useful (sometimes) with directors\n\ + -nortti - Disable the use of the native C++ RTTI with directors\n\ -modern - Use modern python features only, without compatibility code\n\ -apply - Use apply() in proxy classes\n\ -new_vwm - New value wrapper mode, use only when everything else fails \n\ @@ -1404,7 +1404,12 @@ public: */ /* Emit the function call */ + Printf(f->code, "try {\n"); emit_action(n,f); + Printf(f->code, "} catch (Swig::DirectorException& e) {\n"); + Printf(f->code, " SWIG_Python_AddErrMesg(e.getMessage(), 1);\n"); + Printf(f->code, " SWIG_fail;\n"); + Printf(f->code, "}\n"); /* This part below still needs cleanup */ @@ -1760,7 +1765,9 @@ public: String *basetype = Getattr(parent, "classtype"); String *target = Swig_method_decl(decl, classname, parms, 0, 0); call = Swig_csuperclass_call(0, basetype, superparms); - Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call); + Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call); + Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype); + Printf(w->def, "}\n"); Delete(target); Wrapper_print(w, f_directors); Delete(call); @@ -1787,11 +1794,14 @@ public: * ------------------------------------------------------------ */ int classDirectorDefaultConstructor(Node *n) { - String *classname; - classname = Swig_class_name(n); + String *classname = Swig_class_name(n); { + Node *parent = Swig_methodclass(n); + String *basetype = Getattr(parent, "classtype"); Wrapper *w = NewWrapper(); - Printf(w->def, "SwigDirector_%s::SwigDirector_%s(PyObject* self) : Swig::Director(self) { }", classname, classname); + Printf(w->def, "SwigDirector_%s::SwigDirector_%s(PyObject* self) : Swig::Director(self) { \n", classname, classname); + Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype); + Printf(w->def, "}\n"); Wrapper_print(w, f_directors); DelWrapper(w); } @@ -2775,13 +2785,19 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { if (!tm) { tm = Getattr(n, "feature:director:except"); } + Printf(w->code, "if (result == NULL) {\n"); + Printf(w->code, " PyObject *error = PyErr_Occurred();\n"); if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { - Printf(w->code, "if (result == NULL) {\n"); - Printf(w->code, " PyObject *error = PyErr_Occurred();\n"); Replaceall(tm, "$error", "error"); Printv(w->code, Str(tm), "\n", NIL); - Printf(w->code, "}\n"); + } else { + Printf(w->code, " if (error != NULL) {\n"); + Printf(w->code, " throw Swig::DirectorMethodException(\"Swig director error detected when calling %s.%s.\\n\");\n", + classname, pyname); + Printf(w->code, " }\n"); } + + Printf(w->code, "}\n"); /* * Python method may return a simple object, or a tuple.