diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index 664ccb7d2..be8392411 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -3825,17 +3825,20 @@ The disadvantage is that invocation of director methods from C++ when Java doesn
With directors routing method calls to Java, and proxies routing them
to C++, the handling of exceptions is an important concern.
-The default behavior from SWIG 3.0
-onwards is to convert the thrown Java exception into a SWIG defined
-DirectorException C++ exception.
-SWIG 2.0 and earlier versions didn't provide any mechanism to handle the Java director method exceptions in C++.
+The default behavior for Java exceptions thrown in a director method overridden in Java is
+to convert the thrown Java exception into a SWIG defined
+DirectorException C++ class exception in the C++ layer and then throw this C++ exception.
-Converting Java exceptions into C++ exceptions can be done in two different ways using
+The conversion of Java exceptions into C++ exceptions can be customized in two different ways using
the director:except feature.
In the simplest approach, a code block is attached to each director method to
handle the mapping of Java exceptions into C++ exceptions.
+The example below converts a
+java.lang.IndexOutOfBoundsException into a C++ std::out_of_range exception and converts a
+user's Java MyJavaException into a C++ MyCppException exception.
+If the Java exception doesn't match either of these, a fallback std::runtime_error C++ exception is thrown.
+A few special variables are expanded from the director:except feature when generated.
+The special variable $error is expanded by SWIG into a unique variable name and
+should be used for the
+assignment of the exception that occurred. The special variable $packagepath is
+replaced by the outer package provided for SWIG generation by the -package option.
+
+Utility functions/classes in director.swg are provided to aid the exception conversion as follows: +
+ +
+namespace Swig {
+
+ // Helper method to determine if a Java throwable matches a particular Java class type
+ bool ExceptionMatches(JNIEnv *jenv, jthrowable throwable, const char *classname);
+
+ // Helper class to extract the exception message from a Java throwable
+ class JavaExceptionMessage {
+ public:
+ JavaExceptionMessage(JNIEnv *jenv, jthrowable throwable);
+
+ // Return a C string of the exception message in the jthrowable passed in the constructor
+ // If no message is available, null_string is return instead
+ const char *message(const char *null_string =
+ "Could not get exception message in JavaExceptionMessage") const;
+ };
+
+ // C++ Exception class for handling Java exceptions thrown during a director method Java upcall
+ class DirectorException : public std::exception {
+ public:
+
+ // Construct exception from a Java throwable
+ DirectorException(JNIEnv *jenv, jthrowable throwable);
+
+ // More general constructor for handling as a java.lang.RuntimeException
+ DirectorException(const char *msg);
+
+ // Return exception message extracted from the Java throwable
+ const char *what() const throw();
+
+ // Reconstruct and raise/throw the Java Exception that caused the DirectorException
+ // Note that any error in the JNI exception handling results in a Java RuntimeException
+ void raiseJavaException(JNIEnv *jenv) const;
+
+ // Create and throw the DirectorException
+ static void raise(JNIEnv *jenv, jthrowable throwable);
+ };
+
+}
+
+
This approach allows a flexible mapping of Java exceptions thrown by director methods into
C++ exceptions expected by a C++ caller. There
@@ -3872,11 +3930,8 @@ type, or derives from the given type, Swig::ExceptionMatches will r
provide the correct fully qualified name, since for wrapped exceptions the
generated proxy class will have additional package qualification, depending on
the '-package' argument and use of the nspace
- feature. The special variable $error is expanded by SWIG into a unique variable name and
-should be used for the
-assignment of the exception that occurred. The special variable $packagepath is
-replaced by the outer package provided for SWIG generation by the -package
-option. The utility class Swig::JavaExceptionMessage is a holder
+ feature.
+The utility class Swig::JavaExceptionMessage is a holder
providing access to the message from the thrown Java exception.
The message() method returns the exception message as a const char *,
which is only valid during the lifetime of the holder. Any code using this message
@@ -3884,20 +3939,20 @@ needs to copy it, for example into a std::string or a newly constructed C++ exce
-Using the above approach to
+Using the above simple approach to
write handlers for a large number of methods will require
repetitive duplication of the director:except feature code.
To mitigate this, an alternative approach is provided via typemaps in a
fashion analagous to
-the "throws" typemap. The
-"throws" typemap provides an approach to automatically map all the C++
+the "throws" typemap.
+The "throws" typemap provides the second approach to map all the C++
exceptions listed in a method's defined exceptions (either from
a C++ exception specification or a %catches
feature) into Java exceptions.
The "directorthrows" typemap provides the inverse mapping and should contain
code to convert a suitably matching Java exception into a C++ exception.
The example below converts a Java java.lang.IndexOutOfBoundsException exception
-to the typemap's type, that is std::out_of_range:
+to the typemap's type, that is a std::out_of_range C++ exception:
@@ -3928,7 +3983,7 @@ is used in the feature code. Consider the following, which also happens to be th
-where Swig::DirectorException::raise is a helper method in the DirectorException class to throw a C++ exception (implemented in director.swg): +where Swig::DirectorException::raise is the helper method to throw a C++ Swig::DirectorException.
%catches as described for the
-Consider the following director method: +Let's try all this together and consider the following director method:
-As can be seen from the generated code below, SWIG generates an exception handler +As can be seen from the resulting generated code below, SWIG generates an exception handler with the catch block comprising the "throws" typemap content.
@@ -2915,8 +2921,7 @@ with the catch block comprising the "throws" typemap content. ... try { bar(); -} -catch(char const *_e) { +} catch(char const *_e) { PyErr_SetString(PyExc_RuntimeError, _e); SWIG_fail; } @@ -2925,8 +2930,8 @@ catch(char const *_e) {-Note that if your methods do not have an exception specification yet they do throw exceptions, SWIG cannot know how to deal with them. -For a neat way to handle these, see the Exception handling with %exception section. +Note that if your methods do not have an exception specification but they do throw exceptions and you are not using %catches, SWIG cannot know how to deal with them. +Please also see the Exception handling with %exception section for another way to handle exceptions.