diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2009-08-18 20:56:02 +0000 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-09-25 16:59:08 +0000 |
commit | 9f8a09ed743cedd9547bf0661d518647966ab114 (patch) | |
tree | 9c7803d3b27a8ec22e91792ac7f7932efa128b20 /Examples/python/exceptproxy/example.i | |
download | swig-tarball-master.tar.gz |
Imported from /srv/lorry/lorry-area/swig-tarball/swig-1.3.40.tar.gz.HEADswig-1.3.40master
Diffstat (limited to 'Examples/python/exceptproxy/example.i')
-rw-r--r-- | Examples/python/exceptproxy/example.i | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/Examples/python/exceptproxy/example.i b/Examples/python/exceptproxy/example.i new file mode 100644 index 0000000..4a1e0ba --- /dev/null +++ b/Examples/python/exceptproxy/example.i @@ -0,0 +1,114 @@ +/* This is a rather sophisticated example that illustrates exception handling, + templates, and proxy classes. + + (i) The %exception directive is used to attach exception handlers + to specific methods. + + (ii) Exception classes are automatically converted to proxy class + objects. + + (iii) The %template directive is used to expand the templates +*/ + +%module example + +%{ +#include "example.h" +%} + +/* Define some exception handlers for specific methods. In + the header file, the enqueue method throws FullError and + the dequeue method throws EmptyError. Since we don't + want to define an exception handler for everything, we + simply write a handler each method individually. + + Note: the *::enqueue syntax means that we simply define + the handler for any class with this method defined. +*/ + +/* + First we need to 'disable' the default swig throw mechanism for the + FullError class. We do this by rethrowing the exception. + + Note that this is necessary since the class appears in a throw + declaration: + + + void enqueue(T x) throw(FullError); + + hence, swig recognizes it as an exception class and it will generate + the necessary code to catch it and rethrow it to the python side. + +*/ +%typemap(throws) FullError "(void)$1; throw;"; + + +%exception *::enqueue { + try { + $action + } catch(FullError& e) { + FullError *ecopy = new FullError(e); + PyObject *err = SWIG_NewPointerObj(ecopy, SWIGTYPE_p_FullError, 1); + PyErr_SetObject(SWIG_Python_ExceptionType(SWIGTYPE_p_FullError), err); + SWIG_fail; + } +} + +/* Some notes about the code above: + + (0) $action gets replaced with the actual method call. + + (1) We are going to return a copy of the exception object (FullError) + to pass back to the Python interpreter. This is why the copy + constructor is being called. + + (2) The SWIG_NewPointerObj() call automatically wraps the exception object + into a proxy class. The SWIGTYPE_p_FullError is the type-descriptor + used for type checking. The "1" indicates that Python will have + ownership of the resulting object. + + (3) The PyErr_SetObject call sets the Python exception. However, + the SWIGTYPE_p_FullError->clientdata reference may not be + obvious. This is actually the Python proxy class object + for FullError. Recall that in Python, exceptions are defined + as classes. Therefore, this works perfectly as the argument to + PyErr_SetObject()! A neat trick perhaps. +*/ + +/* + Now, the EmpytError doesn't appear in a throw declaration, and hence + we need to 'mark' it as an exception class. In python, classes that + are used as exception are 'special', and need to be wrapped as + 'classic' ones. + + This is a python issue, and if you don't mark the class, you will + see 'interesting' behaviours at the python side. + + +*/ +%exceptionclass EmptyError; +%exceptionclass FullError; + +%exception *::dequeue { + try { + $action + } catch(EmptyError& e) { + EmptyError *ecopy = new EmptyError(e); + PyObject *err = SWIG_NewPointerObj(ecopy, SWIGTYPE_p_EmptyError, 1); + PyErr_SetObject(SWIG_Python_ExceptionType(SWIGTYPE_p_EmptyError), err); + SWIG_fail; + } +} + +/* Grab the original header file */ +%include "example.h" + +/* Instantiate a few templates */ + +%template(intQueue) Queue<int>; +%template(doubleQueue) Queue<double>; + + + + + |