Documentation edit for the director:except feature and directorthrows typemap
This commit is contained in:
parent
9df7bee570
commit
d73f04e925
2 changed files with 200 additions and 131 deletions
|
|
@ -3556,99 +3556,108 @@ However, if all director methods are expected to usually be overridden by Java s
|
||||||
The disadvantage is that invocation of director methods from C++ when Java doesn't actually override the method will require an additional call up into Java and back to C++. As such, this option is only useful when overrides are extremely common and instantiation is frequent enough that its performance is critical.
|
The disadvantage is that invocation of director methods from C++ when Java doesn't actually override the method will require an additional call up into Java and back to C++. As such, this option is only useful when overrides are extremely common and instantiation is frequent enough that its performance is critical.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H3><a name="Java_exceptions_from_directors"></a>24.5.7 Java Exceptions from Directors</H3>
|
<H3><a name="Java_exceptions_from_directors"></a>24.5.7 Java exceptions from directors</H3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
With directors routing method calls to Java, and proxies routing them
|
With directors routing method calls to Java, and proxies routing them
|
||||||
to C++, the handling of exceptions is an important concern. In Swig
|
to C++, the handling of exceptions is an important concern.
|
||||||
2.0, the director class methods ignored java exceptions that occurred
|
The default behavior from SWIG 3.0
|
||||||
during method calls dispatched to the Java director class and simply
|
onwards is to convert the thrown Java exception into a SWIG defined
|
||||||
returned '$null' to the C++ caller. The default behavior now throws a
|
<code>DirectorException</code> C++ exception.
|
||||||
Swig-defined <code>DirectorException</code> C++ exception. A facility
|
SWIG 2.0 and earlier versions didn't provide any mechanism to handle the Java director method exceptions in C++.
|
||||||
is now provided to allow translation of thrown Java exceptions into
|
</p>
|
||||||
C++ exceptions. This can be done in two different ways using
|
|
||||||
the <code>%feature("director:except")</code> directive. In the
|
<p>
|
||||||
simplest approach, a code block is attached to each director method to
|
Converting Java exceptions into C++ exceptions can be done in two different ways using
|
||||||
handle the mapping of java exceptions into C++ exceptions.
|
the <code>director:except</code> <a href="Customization.html#Customization_features">feature</a>.
|
||||||
|
In the simplest approach, a code block is attached to each director method to
|
||||||
|
handle the mapping of Java exceptions into C++ exceptions.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
// All the rules to associate a feature with an element apply
|
|
||||||
%feature("director:except") MyClass::method(int x) {
|
%feature("director:except") MyClass::method(int x) {
|
||||||
jthrowable $error = jenv->ExceptionOccurred();
|
jthrowable $error = jenv->ExceptionOccurred();
|
||||||
if ($error) {
|
if ($error) {
|
||||||
jenv->ExceptionClear();
|
jenv->ExceptionClear();
|
||||||
if (Swig::ExceptionMatches(jenv,$error,"java/lang/IndexOutOfBoundsException"))
|
if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException"))
|
||||||
throw std::out_of_range(Swig::JavaExceptionMessage(jenv,$error).message());
|
throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||||
else if (Swig::ExceptionMatches(jenv,$error,"$packagepath/MyJavaException"))
|
if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyJavaException"))
|
||||||
throw MyCppException(Swig::JavaExceptionMessage(jenv,$error).message());
|
throw MyCppException(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||||
else
|
throw std::runtime_error("Unexpected exception thrown in MyClass::method");
|
||||||
throw std::runtime_error("Unexpected exception thrown by MyClass::method");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyClass {
|
class MyClass {
|
||||||
void method(int x); /* on C++ side, may get std::runtime_error or MyCppException */
|
/** Throws either a std::out_of_range or MyCppException on error */
|
||||||
|
void method(int x);
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This approach allows mapping java exceptions thrown by director methods into
|
This approach allows a flexible mapping of Java exceptions thrown by director methods into
|
||||||
C++ exceptions, to match the exceptions expected by a C++ caller. There
|
C++ exceptions expected by a C++ caller. There
|
||||||
need not be any exception specification on the method. This approach gives
|
need not be any C++ <em>exception specifications</em> on the C++ method. The
|
||||||
complete flexibility to map exceptions thrown by a java director
|
utility function <code>Swig::ExceptionMatches</code>
|
||||||
implementation into desired C++ exceptions. The
|
|
||||||
function <code>Swig::ExceptionMatches</code>
|
|
||||||
and class <code>Swig::JavaExceptionMessage</code> are provided to simplify
|
and class <code>Swig::JavaExceptionMessage</code> are provided to simplify
|
||||||
writing code for wrappers that use <code>director:except</code>feature. These simplify
|
writing code for wrappers that use the <code>director:except</code> feature. The
|
||||||
testing the type of the java exception and constructing C++ exceptions. The
|
|
||||||
function <code>Swig::ExceptionMatches</code> matches the type of the
|
function <code>Swig::ExceptionMatches</code> matches the type of the
|
||||||
<code>jthrowable</code> thrown against a <b>fully qualified</b> JNI style class
|
<code>jthrowable</code> thrown against a <b>fully qualified</b> JNI style class
|
||||||
name, like <code>"java/lang/IOError"</code>. If the throwable class is the same
|
name, such as <code>"java/lang/IOError"</code>. If the throwable class is the same
|
||||||
type, or derives from the given type, it returns true. Care must be taken to
|
type, or derives from the given type, <code>Swig::ExceptionMatches</code> will return true. Care must be taken to
|
||||||
provide the correct fully qualified name, since for wrapped exceptions the
|
provide the correct fully qualified name, since for wrapped exceptions the
|
||||||
generated proxy class will have additional package qualification, depending on
|
generated proxy class will have additional package qualification, depending on
|
||||||
the '-package' argument and use of <a href="#Java_namespaces">nspace
|
the '-package' argument and use of the <a href="#Java_namespaces">nspace
|
||||||
feature</a>. The variable $error is simply a unique variable name to allow
|
feature</a>. The special variable <code>$error</code> is expanded by SWIG into a unique variable name and
|
||||||
assignment of the exception that occurred. The variable $packagepath is
|
should be used for the
|
||||||
replaced by the outer package provided for swig generation by the -package
|
assignment of the exception that occurred. The special variable <code>$packagepath</code> is
|
||||||
option. The class <code>Swig::JavaExceptionMessage</code> is a holder
|
replaced by the outer package provided for SWIG generation by the -package
|
||||||
object giving access to the message from the thrown java exception.
|
option. The utility class <code>Swig::JavaExceptionMessage</code> is a holder
|
||||||
The message() method returns the exception message as a <code>const char *</code>,
|
providing access to the message from the thrown Java exception.
|
||||||
|
The <code>message()</code> method returns the exception message as a <code>const char *</code>,
|
||||||
which is only valid during the lifetime of the holder. Any code using this message
|
which is only valid during the lifetime of the holder. Any code using this message
|
||||||
needs to copy it, for example into a std::string or a newly constructed C++ exception.
|
needs to copy it, for example into a std::string or a newly constructed C++ exception.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If many methods may throw different exceptions, using this approach to
|
Using the above approach to
|
||||||
write handlers for a large number of methods will result in
|
write handlers for a large number of methods will require
|
||||||
duplication of the code in the <code>director:except</code> feature
|
repetitive duplication of the <code>director:except</code> feature code.
|
||||||
code blocks, and will require separate feature definitions for every
|
To mitigate this, an alternative approach is provided via typemaps in a
|
||||||
method. So an alternative approach is provided, using typemaps in a
|
|
||||||
fashion analagous to
|
fashion analagous to
|
||||||
the <a href="Typemaps.html#throws_typemap">"throws" typemap.</a> The
|
the <a href="Typemaps.html#throws_typemap">"throws" typemap.</a> The
|
||||||
"throws" typemap provides an approach to automatically map all the C++
|
"throws" typemap provides an approach to automatically map all the C++
|
||||||
exceptions listed in a method's defined exceptions (either from
|
exceptions listed in a method's defined exceptions (either from
|
||||||
an <em>exception specification</em> or a <code>%catches</code>
|
a C++ <em>exception specification</em> or a <code>%catches</code>
|
||||||
feature) into Java exceptions, for the generated proxy classes. To
|
feature) into Java exceptions.
|
||||||
provide the inverse mapping, the <code>directorthrows</code> typemap
|
The "directorthrows" typemap provides the inverse mapping and should contain
|
||||||
is provided.
|
code to convert a suitably matching Java exception into a C++ exception.
|
||||||
|
The example below converts a Java <code>java.lang.IndexOutOfBoundsException</code> exception
|
||||||
|
to the typemap's type, that is <code>std::out_of_range</code>:
|
||||||
|
|
||||||
<p>Using directorthrows typemaps allows a
|
<div class="code">
|
||||||
generic <code>director:except</code> feature to be combined with
|
<pre>
|
||||||
method-specific handling to achieve the desired result. The
|
%typemap(directorthrows) std::out_of_range %{
|
||||||
default <code>director:except</code> feature, in combination
|
if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException")) {
|
||||||
with <code>directorthrows</code> typemaps generate exception mapping
|
throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||||
to C++ exceptions for all the exceptions defined for each method. The
|
}
|
||||||
default definition is shown below.</p>
|
%}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The "directorthrows" typemap is then used in conjunction with the
|
||||||
|
<code>director:except</code> feature if the <code>$directorthrowshandlers</code> special variable
|
||||||
|
is used in the feature code. Consider the following, which also happens to be the default:
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
%feature("director:except") %{
|
%feature("director:except") %{
|
||||||
jthrowable $error = jenv->ExceptionOccurred();
|
jthrowable $error = jenv->ExceptionOccurred();
|
||||||
if ($error) {
|
if ($error) {
|
||||||
jenv->ExceptionClear();
|
jenv->ExceptionClear();
|
||||||
$directorthrowshandlers
|
$directorthrowshandlers
|
||||||
throw Swig::DirectorException(jenv, $error);
|
throw Swig::DirectorException(jenv, $error);
|
||||||
}
|
}
|
||||||
|
|
@ -3657,34 +3666,66 @@ default definition is shown below.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>The code generated using the <code>director:except</code> feature
|
<p>The code generated using the <code>director:except</code> feature
|
||||||
replaces the <code>$directorthrowshandlers</code> with code that throws
|
replaces the <code>$directorthrowshandlers</code> special variable with the code in
|
||||||
appropriate C++ exceptions from <code>directorthrows</code> typemaps
|
the "directorthrows" typemaps, for each and every exception defined for the method.
|
||||||
for each exception defined for the method. Just as with
|
The possible exceptions can be defined either with a C++ exception
|
||||||
the <a href="Typemaps.html#throws_typemap">"throws" typemap</a>, the
|
specification or <code>%catches</code> as described for the
|
||||||
possible exceptions may be defined either with an exception
|
<a href="Typemaps.html#throws_typemap">"throws" typemap</a>.
|
||||||
specification (<code> throw(MyException,std::runtime_error)</code> ) or
|
</p>
|
||||||
using the <code>%catches</code> feature applied to the method.</p>
|
|
||||||
|
|
||||||
<p><em>Note: Using the %catches feature to define the
|
<p>
|
||||||
handled exceptions is preferred to using exception specifications. If
|
Consider the following director method:
|
||||||
the interface is defined with an exception specification the generated
|
</p>
|
||||||
swig proxy classes will have the same exception specification. In C++
|
|
||||||
if exceptions other than those in the specification are thrown, the
|
|
||||||
program will be terminated. </em></p>
|
|
||||||
|
|
||||||
<p>Because this default definition maps any unhandled java exceptions to
|
<div class="code">
|
||||||
Swig::DirectorException, any director methods that define exception
|
<pre>
|
||||||
specifications will cause program termination. To simply ignore
|
...
|
||||||
unexpected exceptions, the default can be changed to:
|
virtual void doSomething(int index) throw (std::out_of_range);
|
||||||
|
...
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When combined with the default <code>director:except</code> feature and the "directorthrows" typemap above,
|
||||||
|
the resulting code generated in the director method after calling up to Java will be:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
jthrowable swigerror = jenv->ExceptionOccurred();
|
||||||
|
if (swigerror) {
|
||||||
|
jenv->ExceptionClear();
|
||||||
|
if (Swig::ExceptionMatches(jenv, swigerror, "java/lang/IndexOutOfBoundsException")) {
|
||||||
|
throw std::out_of_range(Swig::JavaExceptionMessage(jenv, swigerror).message());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Swig::DirectorException(jenv, swigerror);
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><em>
|
||||||
|
Note: Beware of using exception specifications as the SWIG director methods
|
||||||
|
will be generated with the same exception specifications and if the
|
||||||
|
director method throws an exception that is not specified it is likely
|
||||||
|
to terminate your program. See the C++ standard for more details.
|
||||||
|
Using the %catches feature instead to define the handled exceptions does not suffer
|
||||||
|
this potential fate.
|
||||||
|
</em></p>
|
||||||
|
|
||||||
|
<p>Because the default code generation maps any unhandled Java exceptions to
|
||||||
|
<code>Swig::DirectorException</code>, any director methods that have exception
|
||||||
|
specifications may cause program termination. To simply ignore
|
||||||
|
unexpected exceptions, the default handling can be changed with:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
%feature("director:except") %{
|
%feature("director:except") %{
|
||||||
jthrowable $error = jenv->ExceptionOccurred();
|
jthrowable $error = jenv->ExceptionOccurred();
|
||||||
if ($error) {
|
if ($error) {
|
||||||
jenv->ExceptionClear();
|
jenv->ExceptionClear();
|
||||||
$directorthrowshandlers
|
$directorthrowshandlers
|
||||||
return $null;
|
return $null; // exception is ignored
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -3692,27 +3733,25 @@ unexpected exceptions, the default can be changed to:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Alternatively an exception compatible with the existing director
|
<p>Alternatively an exception compatible with the existing director
|
||||||
method exception specifications may be thrown. Assuming that all
|
method exception specifications can be thrown. Assuming that all
|
||||||
methods allow std::runtime_error to be thrown,
|
methods allow std::runtime_error to be thrown,
|
||||||
the <code>return $null;</code> could be changed to:
|
the <code>return $null;</code> could be changed to:
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
throw std::runtime_error(Swig::JavaExceptionMessage(jenv,$error).message());
|
throw std::runtime_error(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>In more complex situations, a separate <code>director:except</code> feature
|
<p>In more complex situations, a separate <code>director:except</code> feature
|
||||||
may need to be attached to specific methods.
|
may need to be attached to specific methods.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Below is a complete example demonstrating the use
|
<p>Below is a complete example demonstrating the use
|
||||||
of <code>directorthrows</code> typemaps. The <code>directorthrows</code> typemap
|
of the "directorthrows" typemaps. In this example, a
|
||||||
provides a code fragment to test for a pending java exception type, and the
|
generic "directorthrows" typemap is appropriate for all three exceptions - all
|
||||||
resulting C++ exception that will be thrown. In this example, a
|
take single string constructors. If the exceptions had different constructors,
|
||||||
generic directorthrows typemap is appropriate for all three exceptions - all
|
|
||||||
take single string constructors. If the constructors had different constructors,
|
|
||||||
it would be neccessary to have separate typemaps for each exception type.
|
it would be neccessary to have separate typemaps for each exception type.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3721,22 +3760,29 @@ it would be neccessary to have separate typemaps for each exception type.
|
||||||
example interface that could be generated and built. -->
|
example interface that could be generated and built. -->
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
|
%module(directors="1") example
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
%}
|
||||||
|
|
||||||
// Define exceptions in header section using std::runtime_error
|
// Define exceptions in header section using std::runtime_error
|
||||||
%define DEFINE_EXCEPTION(NAME)
|
%define DEFINE_EXCEPTION(NAME)
|
||||||
%{
|
%{
|
||||||
#include <exception>
|
|
||||||
namespace MyNS {
|
namespace MyNS {
|
||||||
struct NAME : public std::runtime_error { NAME(const std::string& what):runtime_error(what) {}; };
|
struct NAME : public std::runtime_error { NAME(const std::string &what) : runtime_error(what) {} };
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
%enddef
|
%enddef
|
||||||
// Expose c++ exceptions as java Exceptions with getMessage
|
|
||||||
|
// Expose C++ exceptions as Java Exceptions by changing the Java base class and providing a getMessage()
|
||||||
%define DECLARE_EXCEPTION(NAME)
|
%define DECLARE_EXCEPTION(NAME)
|
||||||
%typemap(javabase) MyNS::NAME "java.lang.Exception";
|
%typemap(javabase) MyNS::NAME "java.lang.Exception";
|
||||||
%rename(getMessage,fullname=1) MyNS::NAME::what;
|
%rename(getMessage) MyNS::NAME::what;
|
||||||
namespace MyNS {
|
namespace MyNS {
|
||||||
struct NAME {
|
struct NAME {
|
||||||
NAME(const std::string& what);
|
NAME(const std::string& what);
|
||||||
const char * what();
|
const char * what();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -3744,17 +3790,16 @@ namespace MyNS {
|
||||||
|
|
||||||
DEFINE_EXCEPTION(ExceptionA)
|
DEFINE_EXCEPTION(ExceptionA)
|
||||||
DEFINE_EXCEPTION(ExceptionB)
|
DEFINE_EXCEPTION(ExceptionB)
|
||||||
DEFINE_EXCEPTION(Unknown)
|
DEFINE_EXCEPTION(Unexpected)
|
||||||
|
|
||||||
// Mark three methods to map director-thrown exceptions.
|
// Mark three methods to map director thrown exceptions.
|
||||||
// Standard rules for feature matching apply
|
|
||||||
%feature("director:except") MyClass::meth1(int);
|
%feature("director:except") MyClass::meth1(int);
|
||||||
%feature("director:except") MyClass::meth2;
|
%feature("director:except") MyClass::meth2;
|
||||||
%feature("director:except") meth3;
|
%feature("director:except") meth3;
|
||||||
|
|
||||||
%typemap(directorthrows) MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected %{
|
%typemap(directorthrows) MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected %{
|
||||||
if (Swig::ExceptionMatches(jenv,$error,"$packagepath/$javaclassname"))
|
if (Swig::ExceptionMatches(jenv, $error, "$packagepath/$javaclassname"))
|
||||||
throw $1_type(Swig::JavaExceptionMessage(jenv,$error).message());
|
throw $1_type(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
DECLARE_EXCEPTION(ExceptionA)
|
DECLARE_EXCEPTION(ExceptionA)
|
||||||
|
|
@ -3769,68 +3814,54 @@ DECLARE_EXCEPTION(Unexpected)
|
||||||
virtual void meth1(int x) throw(MyNS::ExceptionA, MyNS::ExceptionB) = 0;
|
virtual void meth1(int x) throw(MyNS::ExceptionA, MyNS::ExceptionB) = 0;
|
||||||
virtual void meth2() = 0; /* throws MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected */
|
virtual void meth2() = 0; /* throws MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected */
|
||||||
virtual void meth3(float x) throw(MyNS::Unexpected) = 0;
|
virtual void meth3(float x) throw(MyNS::Unexpected) = 0;
|
||||||
virtual ~MyClass() {};
|
virtual ~MyClass() {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In this case the three different <code>directorthrows</code> typemaps will be used
|
In this case the three different "directorthrows" typemaps will be used
|
||||||
to generate the three different exception handlers for
|
to generate the three different exception handlers for
|
||||||
<code>meth1</code>, <code>meth2</code> and <code>meth3</code>. The generated
|
<code>meth1</code>, <code>meth2</code> and <code>meth3</code>. The generated
|
||||||
handlers will have "if" blocks for each exception type specified, in
|
handlers will have "if" blocks for each exception type specified, in
|
||||||
the exception specification or <code>%catches</code> feature. The code block
|
the exception specification or <code>%catches</code> feature.
|
||||||
in the directorthrows typemap should always throw a c++ exception.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Note that the <code>directorthrows</code> typemaps are important
|
<p>Note that the "directorthrows" typemaps are important
|
||||||
only if it is important for the the exceptions passed through the C++
|
only if it is important for the the exceptions passed through the C++
|
||||||
layer to be mapped to distinct C++ exceptions. If director methods
|
layer to be mapped to distinct C++ exceptions. If director methods
|
||||||
are being called by C++ code that is itself wrapped in a
|
are being called by C++ code that is itself wrapped in a
|
||||||
Swig-generated java wrapper and access is always through this wrapper,
|
SWIG generated Java wrapper and access is always through this wrapper,
|
||||||
the default Swig::DirectorException class provides enough information
|
the default <code>Swig::DirectorException</code> class provides enough information
|
||||||
to reconstruct the original exception. In this case removing the
|
to reconstruct the original exception. In this case removing the
|
||||||
$directorthrowshandlers replacement variable from the
|
<code>$directorthrowshandlers</code> special variable from the
|
||||||
default <code>director:except</code> feature and simply always
|
default <code>director:except</code> feature and simply always
|
||||||
throwing a Swig::DirectorException will achieve the desired result.
|
throwing a <code>Swig::DirectorException</code> will achieve the desired result.
|
||||||
Along with this a generic exception feature is added to convert any
|
Along with this a generic exception feature is added to convert any
|
||||||
caught <code>Swig::DirectorException</code>s back into the underlying
|
caught <code>Swig::DirectorException</code>s back into the underlying
|
||||||
java exceptions, for each method which may get a generic
|
Java exceptions via the <code>Swig::DirectorException::raiseJavaException</code> method,
|
||||||
DirectorException from a wrapped director method.</p>
|
as demonstrated with <code>%javaexception</code> below:
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
%feature ("except",throws="Exception") MyClass::myMeth %{
|
%javaexception("Exception") MyClass::myMethod %{
|
||||||
try { $action }
|
try {
|
||||||
catch (Swig::DirectorException & direxcp) {
|
$action
|
||||||
// jenv always available in JNI code
|
} catch (Swig::DirectorException &e) {
|
||||||
// raise the java exception that originally caused the DirectorException
|
// raise/throw the Java exception that originally caused the DirectorException
|
||||||
direxcp.raiseJavaException(jenv);
|
e.raiseJavaException(jenv);
|
||||||
return $null;
|
return $null;
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>The <code>throws="Exception"</code> attribute on the exception
|
<p>
|
||||||
feature is necessary if any of the translated exceptions will be
|
See the <a href="#Java_exception_handling">Exception handling with %exception and %javaexception</a>
|
||||||
checked exceptions, since the java compiler will otherwise assert that
|
section for more on converting C++ exceptions to Java exceptions.
|
||||||
no checked exceptions can be thrown by the method. This may be more
|
</p>
|
||||||
specific that the completely generic "Exception" class, of course. A
|
|
||||||
similar feature must be added to director methods to allow checked
|
|
||||||
exceptions to be thrown from the director method implementations.
|
|
||||||
Here, no actual exception handling is needed - the feature simply
|
|
||||||
is being used to add a generic checked exception signature to the
|
|
||||||
generated director method wrapper. </p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
%feature ("except",throws="Exception") MyDirectorClass::myDirMeth %{ %}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<H2><a name="Java_allprotected"></a>24.6 Accessing protected members</H2>
|
<H2><a name="Java_allprotected"></a>24.6 Accessing protected members</H2>
|
||||||
|
|
||||||
|
|
@ -5643,7 +5674,7 @@ can be wrapped with the Java equivalent, that is, static inner proxy classes.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b><tt>$jniinput, $javacall and $packagepath</tt></b><br>
|
<b><tt>$error, $jniinput, $javacall and $packagepath</tt></b><br>
|
||||||
These special variables are used in the directors typemaps. See <a href="#Java_directors_typemaps">Director specific typemaps</a> for details.
|
These special variables are used in the directors typemaps. See <a href="#Java_directors_typemaps">Director specific typemaps</a> for details.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -5977,6 +6008,10 @@ is the package name passed from the SWIG command line and <code>$javaclassname</
|
||||||
If the <tt>-package</tt> commandline option is not used to specify the package, then '$packagepath/' will be removed from the resulting output JNI field descriptor.
|
If the <tt>-package</tt> commandline option is not used to specify the package, then '$packagepath/' will be removed from the resulting output JNI field descriptor.
|
||||||
<b>Do not forget the terminating ';' for JNI field descriptors starting with 'L'.</b>
|
<b>Do not forget the terminating ';' for JNI field descriptors starting with 'L'.</b>
|
||||||
If the ';' is left out, Java will generate a "method not found" runtime error.
|
If the ';' is left out, Java will generate a "method not found" runtime error.
|
||||||
|
Note that the <code>$packagepath</code> substitution always uses the path separator '/' when expanded.
|
||||||
|
The <code>$javaclassname</code> expansion can be confusing as it is normally expanded using the '.' separator.
|
||||||
|
However, <code>$javaclassname</code> is expanded using the path separator '/' in typemap's "descriptor" attribute
|
||||||
|
as well as in the "directorthrows" typemap.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -6072,6 +6107,40 @@ The target method is the method in the Java proxy class which overrides the virt
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p><tt>%typemap(directorthrows)</tt></p>
|
||||||
|
<div class="indent">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Conversion of Java exceptions to C++ exceptions in director method's exception handling.
|
||||||
|
This typemap is expected to test the <tt>$error</tt> special variable for a matching Java exception
|
||||||
|
and if successful convert and throw it into a C++ exception given by the typemap's type.
|
||||||
|
The <code>$error</code> special variable is of type <code>jthrowable</code> and is
|
||||||
|
substituted with a unique variable name in the generated code.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The example below converts a Java <code>java.lang.IndexOutOfBoundsException</code> exception
|
||||||
|
to the typemap's type, that is <code>std::out_of_range</code>:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%typemap(directorthrows) std::out_of_range %{
|
||||||
|
if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException")) {
|
||||||
|
throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The utility function <code>Swig::ExceptionMatches</code>
|
||||||
|
and class <code>Swig::JavaExceptionMessage</code> are helpers available when using directors and are described
|
||||||
|
in the <a href="#Java_exceptions_from_directors">Java Exceptions from Directors</a> section.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<p><tt>%typemap(javapackage)</tt></p>
|
<p><tt>%typemap(javapackage)</tt></p>
|
||||||
<div class="indent">
|
<div class="indent">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,7 @@ example.i(4) : Syntax error in input.
|
||||||
<li>474. Method <em>method</em> usage of the optimal attribute ignored in the out typemap as the following cannot be used to generate optimal code: <em>code</em>
|
<li>474. Method <em>method</em> usage of the optimal attribute ignored in the out typemap as the following cannot be used to generate optimal code: <em>code</em>
|
||||||
<li>475. Multiple calls to <em>method</em> might be generated due to optimal attribute usage in the out typemap.
|
<li>475. Multiple calls to <em>method</em> might be generated due to optimal attribute usage in the out typemap.
|
||||||
<li>476. Initialization using std::initializer_list.
|
<li>476. Initialization using std::initializer_list.
|
||||||
<li>477. Feature director:except on <em>Class::method</em> with $directorthrowshandlers requires directorthrows typemap for exception <em>Exception</em>
|
<li>477. No directorthrows typemap defined for <em>type</em>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue