Since all methods can now throw sidl.RuntimeException , Babel ensures there is an out argument to hold an exception. If not explicitly specified, Babel will automatically add the argument. For maximum backward compatibility, the base exception argument type is sidl.BaseInterface, while the base exception class is sidl.SIDLException. The exception argument appears after the return value when both occur in a method.
After the call, the client should test this argument. If a function does not test the exception argument, thrown exceptions will be utterly ignored -- not propagated to higher level functions. If the exception parameter is non-zero, an exception was thrown by the method, and the caller should respond appropriately. When an exception is thrown, the value of all other arguments is undefined (so should be ignored).
One approach to exception handling is to pass the exception on to the
caller. In this case, sidl.BaseException.add
should be called to add another line in the stack trace for the exception.
sidl.BaseException defines two methods that can be helpful when
reporting exceptions to end users getNote and
getTrace. getNote often provides some indication of what
went wrong. Its contents are provided by the implementor of the
called function, so it can be empty. Similarly, getTrace
provides a summary of the call stack. Again,
implementors are responsible for providing the information.
Alternatively, the caller could try to determine which exception was thrown through casting the argument. A successful cast indicates the type of exception that has occurred. An example of this process is illustrated below, though not all exceptions associated with the method are checked. The SIDL specification and corresponding FORTRAN 77 API are given in Section 8.2.2.
integer*8 fib, except, except2, except3 integer*4 index, maxdepth, maxval, depth, result call ExceptionTest_Fib__create_f(fib, except) if (except .ne. 0) then C do something with a runtime exception endif index = 4 maxdepth = 100 maxvalue = 32000 depth = 0 call ExceptionTest_getFib_f(fib, index, maxdepth, $ maxvalue, depth, result, except) if (except .ne. 0) then call ExceptionTest_FibException__cast_f(except, except2, except3) if (except2 .ne. 0) then c do something here with the FibException call ExceptionTest_FibException_deleteRef_f(except2, except3) else call ExceptionTest_NegativeValueException__cast_f $ (exception, except2, except3) c do something here with the NegativeValueException call ExceptionTest_NegativeValueException_ $ deleteRef_f(except2, except3) endif call sidl_BaseException_deleteRef_f(except, except3) else write (*,*) 'getFib for ', index, ' returned ', result endif call ExceptionTest_Fib_deleteRef_f(fib, except)
If one of the possible exception types is a subclass of another, casting to the subclass should be attempted before casting to the superclass -- assuming that the distinction between the two exception types results in different exception recovery behavior.