From ca7159f7e719d4d5ddbe9655fcf797cc686383ea Mon Sep 17 00:00:00 2001 From: Marcelo Matus Date: Mon, 7 Mar 2005 20:47:55 +0000 Subject: [PATCH] add better director+exception support git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7038 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Lib/python/director.swg | 21 ++++++-- Lib/python/director_h.swg | 84 ++++++++++++++++++++++++++----- Lib/python/pyinit.swg | 101 ++++++++++++++++++++++---------------- Lib/python/pyptrtypes.swg | 6 +-- Lib/python/pyrun.swg | 75 ++++++++++++++-------------- Lib/python/pyswigtype.swg | 4 +- Lib/python/pyvaltypes.swg | 6 +-- Lib/python/pyvoid.swg | 2 +- Source/Modules/python.cxx | 12 +++-- 9 files changed, 203 insertions(+), 108 deletions(-) diff --git a/Lib/python/director.swg b/Lib/python/director.swg index 530457653..995184aea 100644 --- a/Lib/python/director.swg +++ b/Lib/python/director.swg @@ -10,10 +10,6 @@ #ifdef __cplusplus namespace Swig { - /* base class for director exceptions */ - DirectorException::~DirectorException() { - } - /* simple thread abstraction for pthreads on win32 */ Director::~Director() { swig_decref(); @@ -27,6 +23,23 @@ namespace Swig { bool Director::swig_mutex_active = false; #endif + + void UnknownExceptionHandler::handler() { + try { + throw; + } catch (DirectorException& e) { + std::cerr << "Swig Director exception caught: "<< e.getMessage() << std::endl; + } catch (std::exception& e) { + std::cerr << "std::exception caught: "<< e.what() << std::endl; + } catch (...) { + std::cerr << "Unknown exception caught." << std::endl; + } + std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl; + std::cerr << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl; + std::cerr << "Now your program will probably be terminated, bye." << std::endl; + throw; + } + } #endif /* __cplusplus */ diff --git a/Lib/python/director_h.swg b/Lib/python/director_h.swg index 9c522cd28..490edce67 100644 --- a/Lib/python/director_h.swg +++ b/Lib/python/director_h.swg @@ -12,6 +12,20 @@ #ifdef __cplusplus #include +#include +#include + + +/* + Use -DSWIG_DIRECTOR_NOUEH if you prefer to avoid the use of the + Undefined Exception Handler provided by swift +*/ +#ifndef SWIG_DIRECTOR_NOUEH +#ifndef SWIG_DIRECTOR_UEH +#define SWIG_DIRECTOR_UEH +#endif +#endif + /* Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the @@ -69,32 +83,63 @@ extern "C" { struct swig_type_info; } -namespace Swig { +namespace Swig { /* base class for director exceptions */ class DirectorException { protected: std::string swig_msg; public: - DirectorException(const char* msg ="") : swig_msg(msg) { + DirectorException(const char* hdr ="", const char* msg ="") + : swig_msg(hdr) { + swig_msg += msg; + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, getMessage()); + } else { + SWIG_Python_AddErrMesg(getMessage(), 1); + } } const char *getMessage() const { return swig_msg.c_str(); } - virtual ~DirectorException(); + static void raise(const char* msg = "") + { + throw DirectorException(msg); + } + }; + + class UnknownExceptionHandler + { + static void handler(); + + public: + +#ifdef SWIG_DIRECTOR_UEH + std::unexpected_handler old; + UnknownExceptionHandler(std::unexpected_handler nh = handler) + { + old = std::set_unexpected(nh); + } + + ~UnknownExceptionHandler() + { + std::set_unexpected(old); + } +#endif }; /* type mismatch in the return value from a python method call */ class DirectorTypeMismatchException : public Swig::DirectorException { public: - DirectorTypeMismatchException(const char* msg="") { - if (!PyErr_Occurred()) { - swig_msg = "Swig director type mismatch: "; - swig_msg += msg; - PyErr_SetString(PyExc_TypeError, getMessage()); - } + DirectorTypeMismatchException(const char* msg="") + : Swig::DirectorException("Swig director type mismatch: ", msg) { + } + + static void raise(const char* msg = "") + { + throw DirectorTypeMismatchException(msg); } }; @@ -102,13 +147,30 @@ namespace Swig { class DirectorMethodException : public Swig::DirectorException { public: DirectorMethodException(const char* msg = "") - : DirectorException(msg) + : DirectorException("Swig director python method error: ", msg) { } + + static void raise(const char* msg = "") + { + throw DirectorMethodException(msg); + } }; /* attempt to call a pure virtual method via a director method */ - class DirectorPureVirtualException : public Swig::DirectorException {}; + class DirectorPureVirtualException : public Swig::DirectorException + { + public: + DirectorPureVirtualException(const char* msg = "") + : DirectorException("Swig director pure virtal method called: ", msg) + { + } + + static void raise(const char* msg = "") + { + throw DirectorPureVirtualException(msg); + } + }; /* simple thread abstraction for pthreads on win32 */ diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index 4c9c0c44a..ce08e6edc 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -76,58 +76,71 @@ swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { return 1; } -SWIGINTERN PyTypeObject varlinktype = { - PyObject_HEAD_INIT(0) - 0, /* Number of items in variable part (ob_size) */ - (char *)"swigvarlink", /* Type name (tp_name) */ - sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ - 0, /* Itemsize (tp_itemsize) */ - 0, /* Deallocator (tp_dealloc) */ - (printfunc) swig_varlink_print, /* Print (tp_print) */ - (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ - (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - 0, /* tp_doc */ +SWIGINTERN PyTypeObject* +swig_varlink_type() { + static char varlink__doc__[] = "Swig var link object"; + static PyTypeObject varlink_type +#if !defined(__cplusplus) + ; + static int type_init = 0; + if (!type_init) { + PyTypeObject tmp +#endif + = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* Number of items in variable part (ob_size) */ + (char *)"swigvarlink", /* Type name (tp_name) */ + sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ + 0, /* Itemsize (tp_itemsize) */ + 0, /* Deallocator (tp_dealloc) */ + (printfunc) swig_varlink_print, /* Print (tp_print) */ + (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ + (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + varlink__doc__, /* tp_doc */ #if PY_VERSION_HEX >= 0x02000000 - 0, /* tp_traverse */ - 0, /* tp_clear */ + 0, /* tp_traverse */ + 0, /* tp_clear */ #endif #if PY_VERSION_HEX >= 0x02010000 - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ #endif #if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ #endif #if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ + 0, /* tp_del */ #endif #ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ + 0,0,0,0 /* tp_alloc -> tp_next */ #endif -}; + }; +#if !defined(__cplusplus) + varlink_type = tmp; + type_init = 1; + } +#endif + return &varlink_type; +} /* Create a variable linking object for use later */ SWIGINTERN PyObject * SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyMem_NEW(swig_varlinkobject,1); + swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); if (result) { - varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */ - result->ob_type = &varlinktype; result->vars = 0; - result->ob_refcnt = 0; - Py_INCREF((PyObject *) result); } return ((PyObject*) result); } @@ -222,13 +235,15 @@ SWIG_Python_FixMethods(PyMethodDef *methods, char *ndoc = (char*)malloc(ldoc + lptr + 10); if (ndoc) { char *buff = ndoc; - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue: (void *)(ci->lvalue); - strncpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; + void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; + if (ptr) { + strncpy(buff, methods[i].ml_doc, ldoc); + buff += ldoc; + strncpy(buff, "swig_ptr: ", 10); + buff += 10; + SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); + methods[i].ml_doc = ndoc; + } } } } diff --git a/Lib/python/pyptrtypes.swg b/Lib/python/pyptrtypes.swg index d5d154d3e..67dc4e278 100644 --- a/Lib/python/pyptrtypes.swg +++ b/Lib/python/pyptrtypes.swg @@ -65,7 +65,7 @@ Type *ptr = 0; int res = $input ? asptr_meth($input, &ptr) : 0; if (!res || !ptr) - throw Swig::DirectorTypeMismatchException("Error converting Python object using asptr_meth"); + Swig::DirectorTypeMismatchException::raise("Error converting Python object when using asptr_meth."); temp = *ptr; $result = &temp; if (res == SWIG_NEWOBJ) delete ptr; @@ -75,7 +75,7 @@ Type *ptr = 0; int res = $input ? asptr_meth($input, &ptr) : 0; if (!res || !ptr) - throw Swig::DirectorTypeMismatchException("Error converting Python object using asptr_meth"); + Swig::DirectorTypeMismatchException::raise("Error converting Python object when using asptr_meth."); $result = *ptr; if (res == SWIG_NEWOBJ) delete ptr; } @@ -84,7 +84,7 @@ Type *ptr = 0; int res = $input ? asptr_meth($input, &ptr) : 0; if (!res || !ptr) - throw Swig::DirectorTypeMismatchException("Error converting Python object using asptr_meth"); + Swig::DirectorTypeMismatchException::raise("Error converting Python object when using asptr_meth."); $result = ptr; if (res == SWIG_NEWOBJ) { /* Possible thread/reentrant problem here! */ diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 21aa537d0..ec5afa7fa 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -105,7 +105,7 @@ PySwigObject_long(PySwigObject *v) } SWIGRUNTIME PyObject * -PySwigObject_format(PySwigObject *v, const char* fmt) +PySwigObject_format(const char* fmt, PySwigObject *v) { PyObject *res = NULL; PyObject *args = PyTuple_New(1); @@ -123,13 +123,13 @@ PySwigObject_format(PySwigObject *v, const char* fmt) SWIGRUNTIME PyObject * PySwigObject_oct(PySwigObject *v) { - return PySwigObject_format(v,"%o"); + return PySwigObject_format("%o",v); } SWIGRUNTIME PyObject * PySwigObject_hex(PySwigObject *v) { - return PySwigObject_format(v,"%x"); + return PySwigObject_format("%x",v); } SWIGRUNTIME int @@ -152,8 +152,8 @@ PySwigObject_dealloc(PySwigObject *self) } SWIGRUNTIME PyTypeObject* -PySwigObject_GetType() { - static char PySwigObject_Type__doc__[] = +PySwigObject_type() { + static char pyswigobject_type__doc__[] = "Swig object carries a C/C++ instance pointer"; static PyNumberMethods PySwigObject_as_number = { @@ -185,11 +185,14 @@ PySwigObject_GetType() { #endif }; - static int type_init = 0; - static PyTypeObject PySwigObject_Type; - + static PyTypeObject pyswigobject_type +#if !defined(__cplusplus) + ; + static int type_init = 0; if (!type_init) { - PyTypeObject tmp = { + PyTypeObject tmp +#endif + = { PyObject_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "PySwigObject", /*tp_name*/ @@ -210,7 +213,7 @@ PySwigObject_GetType() { (reprfunc)PySwigObject_str, /*tp_str*/ /* Space for future expansion */ 0,0,0,0, - PySwigObject_Type__doc__, /* Documentation string */ + pyswigobject_type__doc__, /* Documentation string */ #if PY_VERSION_HEX >= 0x02000000 0, /* tp_traverse */ 0, /* tp_clear */ @@ -229,21 +232,22 @@ PySwigObject_GetType() { 0,0,0,0 /* tp_alloc -> tp_next */ #endif }; - - PySwigObject_Type = tmp; +#if !defined(__cplusplus) + pyswigobject_type = tmp; type_init = 1; } - - return &PySwigObject_Type; +#endif + return &pyswigobject_type; } SWIGRUNTIME PyObject * PySwigObject_FromVoidPtrAndDesc(void *ptr, const char *desc) { - PySwigObject *self = PyObject_NEW(PySwigObject, PySwigObject_GetType()); - if (self == NULL) return NULL; - self->ptr = ptr; - self->desc = desc; + PySwigObject *self = PyObject_NEW(PySwigObject, PySwigObject_type()); + if (self) { + self->ptr = ptr; + self->desc = desc; + } return (PyObject *)self; } @@ -261,7 +265,7 @@ PySwigObject_GetDesc(PyObject *self) SWIGRUNTIMEINLINE int PySwigObject_Check(PyObject *op) { - return ((op)->ob_type == PySwigObject_GetType()) + return ((op)->ob_type == PySwigObject_type()) || (strcmp((op)->ob_type->tp_name,"PySwigObject") == 0); } @@ -335,14 +339,17 @@ PySwigPacked_dealloc(PySwigPacked *self) } SWIGRUNTIME PyTypeObject* -PySwigPacked_GetType() { - static char PySwigPacked_Type__doc__[] = +PySwigPacked_type() { + static char pyswigpacked_type__doc__[] = "Swig object carries a C/C++ instance pointer"; - static int type_init = 0; - - static PyTypeObject PySwigPacked_Type; + static PyTypeObject pyswigpacked_type +#if !defined(__cplusplus) + ; + static int type_init = 0; if (!type_init) { - PyTypeObject tmp = { + PyTypeObject tmp +#endif + = { PyObject_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "PySwigPacked", /*tp_name*/ @@ -363,7 +370,7 @@ PySwigPacked_GetType() { (reprfunc)PySwigPacked_str, /*tp_str*/ /* Space for future expansion */ 0,0,0,0, - PySwigPacked_Type__doc__, /* Documentation string */ + pyswigpacked_type__doc__, /* Documentation string */ #if PY_VERSION_HEX >= 0x02000000 0, /* tp_traverse */ 0, /* tp_clear */ @@ -382,20 +389,18 @@ PySwigPacked_GetType() { 0,0,0,0 /* tp_alloc -> tp_next */ #endif }; - - PySwigPacked_Type = tmp; +#if !defined(__cplusplus) + pyswigpacked_type = tmp; type_init = 1; } - - - - return &PySwigPacked_Type; +#endif + return &pyswigpacked_type; } SWIGRUNTIME PyObject * PySwigPacked_FromDataAndDesc(void *ptr, size_t size, const char *desc) { - PySwigPacked *self = PyObject_NEW(PySwigPacked, PySwigPacked_GetType()); + PySwigPacked *self = PyObject_NEW(PySwigPacked, PySwigPacked_type()); if (self == NULL) { return NULL; } else { @@ -428,7 +433,7 @@ PySwigPacked_GetDesc(PyObject *self) SWIGRUNTIMEINLINE int PySwigPacked_Check(PyObject *op) { - return ((op)->ob_type == PySwigPacked_GetType()) + return ((op)->ob_type == PySwigPacked_type()) || (strcmp((op)->ob_type->tp_name,"PySwigPacked") == 0); } @@ -593,7 +598,6 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) #endif type_check: - if (ty) { tc = SWIG_TypeCheck(c,ty); if (!tc) goto type_error; @@ -601,7 +605,6 @@ type_check: } else { *ptr = vptr; } - if ((pyobj) && (flags & SWIG_POINTER_DISOWN)) { PyObject_SetAttrString(pyobj,(char*)"thisown",Py_False); } diff --git a/Lib/python/pyswigtype.swg b/Lib/python/pyswigtype.swg index 0769acb40..81d270400 100644 --- a/Lib/python/pyswigtype.swg +++ b/Lib/python/pyswigtype.swg @@ -288,13 +288,13 @@ %typemap(directorout) SWIGTYPE ($<ype argp) "if (!$input || (SWIG_ConvertPtr($input, (void **)(&argp), $&descriptor, SWIG_POINTER_EXCEPTION | $disown)) == -1) - throw Swig::DirectorTypeMismatchException(\"Pointer conversion failed.\"); + Swig::DirectorTypeMismatchException::raise(\"Pointer conversion failed.\"); $result = *argp;"; %typemap(directorout) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "if (!$input || (SWIG_ConvertPtr($input,(void **)(&$result), $descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) - throw Swig::DirectorTypeMismatchException(\"Pointer conversion failed.\");"; + Swig::DirectorTypeMismatchException::raise(\"Pointer conversion failed.\");"; /* ------------------------------------------------------------ diff --git a/Lib/python/pyvaltypes.swg b/Lib/python/pyvaltypes.swg index a07e8eb67..7033e771c 100644 --- a/Lib/python/pyvaltypes.swg +++ b/Lib/python/pyvaltypes.swg @@ -71,12 +71,12 @@ %typemap(directorargout,fragment=pyfrag) Type *DIRECTOROUT { if ($input) *$result = SWIG_static_cast(SWIG_arg(as_meth($input)),$type); if (!$input || PyErr_Occurred()) - throw Swig::DirectorTypeMismatchException("Error converting Python object using as_meth"); + Swig::DirectorTypeMismatchException::raise("Error converting Python object when using as_meth."); } %typemap(directorout,fragment=pyfrag) Type { if ($input) $result = SWIG_static_cast(SWIG_arg(as_meth($input)),$type); if (!$input || PyErr_Occurred()) - throw Swig::DirectorTypeMismatchException("Error converting Python object using as_meth"); + Swig::DirectorTypeMismatchException::raise("Error converting Python object when using as_meth."); } %typemap(directorout,fragment=pyfrag,warning="470:Using thread/reentrant unsafe wrapping, consider using a plain '"#Type"' return type instead.") const Type& { if ($input) { @@ -84,7 +84,7 @@ $result = &temp; } if (!$input || PyErr_Occurred()) - throw Swig::DirectorTypeMismatchException("Error converting Python object using as_meth"); + Swig::DirectorTypeMismatchException::raise("Error converting Python object when using as_meth."); } %typemap(directorout,fragment=pyfrag) Type &DIRECTOROUT = Type %enddef diff --git a/Lib/python/pyvoid.swg b/Lib/python/pyvoid.swg index da66630dc..572cb1316 100644 --- a/Lib/python/pyvoid.swg +++ b/Lib/python/pyvoid.swg @@ -42,7 +42,7 @@ %typemap(directorout) void * { if (!$input || (SWIG_ConvertPtr($input,(void **)(&$result), 0, SWIG_POINTER_EXCEPTION | $disown )) == -1) - throw Swig::DirectorTypeMismatchException("Pointer conversion failed."); + Swig::DirectorTypeMismatchException::raise("Pointer conversion failed."); } diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index e2be45f1c..0493ccd3a 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1406,13 +1406,13 @@ public: /* Emit the function call */ if (directorsEnabled()) { Printf(f->code, "try {\n"); + Printf(f->code, " Swig::UnknownExceptionHandler dh;\n"); } emit_action(n,f); if (directorsEnabled()) { 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"); } @@ -2758,7 +2758,8 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { /* direct call to superclass if _up is set */ Printf(w->code, "if (swig_get_up()) {\n"); if (pure_virtual) { - Printf(w->code, "throw Swig::DirectorPureVirtualException();\n"); + Printf(w->code, + "Swig::DirectorPureVirtualException::raise(\"%s.\");\n",Swig_method_call(super,l)); } else { if (is_void) { Printf(w->code, "%s;\n", Swig_method_call(super,l)); @@ -2779,7 +2780,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Printf(w->code, "swig_set_inner(\"%s\", true);\n", name); Printf(w->code, "if (!swig_get_self()) {\n"); - Printf(w->code, " throw Swig::DirectorException(\"Swig director 'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname); + Printf(w->code, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname); Printf(w->code, "}\n"); if (Len(parse_args) > 0) { Printf(w->code, "result = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n", pyname, parse_args, arglist); @@ -2802,7 +2803,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Printv(w->code, Str(tm), "\n", NIL); } else { Printf(w->code, " if (error != NULL) {\n"); - Printf(w->code, " throw Swig::DirectorMethodException(\"Swig director error detected when calling %s.%s.\\n\");\n", + Printf(w->code, " Swig::DirectorMethodException::raise(\"Error detected when calling %s.%s.\\n\");\n", classname, pyname); Printf(w->code, " }\n"); } @@ -2824,7 +2825,8 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { if (outputs > 1) { Wrapper_add_local(w, "output", "PyObject *output"); Printf(w->code, "if (!PyTuple_Check(result)) {\n"); - Printf(w->code, "throw Swig::DirectorTypeMismatchException(\"Python method failed to return a tuple.\");\n"); + Printf(w->code, " Swig::DirectorTypeMismatchException::raise(\"Python method %s.%sfailed to return a tuple.\");\n", + classname, pyname); Printf(w->code, "}\n"); }