Merge branch 'master' into doxygen
This commit is contained in:
commit
b7f78dd5a7
232 changed files with 5648 additions and 2419 deletions
|
|
@ -2019,37 +2019,50 @@ public class Container : global::System.IDisposable {
|
|||
// Ensure that the GC doesn't collect any Element set from C#
|
||||
// as the underlying C++ class stores a shallow copy
|
||||
private Element elementReference;
|
||||
private global::System.Runtime.InteropServices.HandleRef getCPtrAndAddReference(Element element) {
|
||||
elementReference = element;
|
||||
return Element.getCPtr(element);
|
||||
}
|
||||
|
||||
public void setElement(Element e) {
|
||||
examplePINVOKE.Container_setElement(swigCPtr, getCPtrAndAddReference(e));
|
||||
examplePINVOKE.Container_setElement(swigCPtr, Element.getCPtr(e));
|
||||
elementReference = e;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The following typemaps will generate the desired code.
|
||||
The 'csin' typemap matches the input parameter type for the <tt>setElement</tt> method.
|
||||
The 'cscode' typemap simply adds in the specified code into the C# proxy class.
|
||||
The following typemaps can be used to generate this code:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%typemap(csin) Element *e "getCPtrAndAddReference($csinput)"
|
||||
|
||||
%typemap(cscode) Container %{
|
||||
// Ensure that the GC doesn't collect any Element set from C#
|
||||
// as the underlying C++ class stores a shallow copy
|
||||
private Element elementReference;
|
||||
private global::System.Runtime.InteropServices.HandleRef getCPtrAndAddReference(Element element) {
|
||||
elementReference = element;
|
||||
return Element.getCPtr(element);
|
||||
}
|
||||
%}
|
||||
|
||||
%typemap(csin,
|
||||
post=" elementReference = $csinput;"
|
||||
) Element *e "Element.getCPtr($csinput)"
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The 'cscode' typemap simply adds in the specified code into the C# proxy class.
|
||||
The 'csin' typemap matches the input parameter type and name for the <tt>setElement</tt> method and
|
||||
the 'post' typemap attribute allows adding code after the PInvoke call.
|
||||
The 'post' code is generated into a finally block after the PInvoke call so the resulting code isn't quite
|
||||
as mentioned earlier, <tt>setElement</tt> is actually:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
public void setElement(Element e) {
|
||||
try {
|
||||
examplePINVOKE.Container_setElement(swigCPtr, Element.getCPtr(e));
|
||||
} finally {
|
||||
elementReference = e;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -269,6 +269,11 @@
|
|||
<li><a href="SWIGPlus.html#SWIGPlus_nn35">Using declarations and inheritance</a>
|
||||
<li><a href="SWIGPlus.html#SWIGPlus_nested_classes">Nested classes</a>
|
||||
<li><a href="SWIGPlus.html#SWIGPlus_const">A brief rant about const-correctness</a>
|
||||
<li><a href="SWIGPlus.html#SWIGPlus_target_language_callbacks">Callbacks to the target language</a>
|
||||
<ul>
|
||||
<li><a href="SWIGPlus.html#SWIGPlus_director_classes_introduction">Introduction to director classes</a>
|
||||
<li><a href="SWIGPlus.html#SWIGPlus_directors_for_function_pointers">Using directors and target language callbacks</a>
|
||||
</ul>
|
||||
<li><a href="SWIGPlus.html#SWIGPlus_nn42">Where to go for more information</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -381,6 +386,7 @@
|
|||
<ul>
|
||||
<li><a href="Library.html#Library_shared_ptr_basics">shared_ptr basics</a>
|
||||
<li><a href="Library.html#Library_shared_ptr_inheritance">shared_ptr and inheritance</a>
|
||||
<li><a href="Library.html#Library_shared_ptr_overloading">shared_ptr and method overloading</a>
|
||||
<li><a href="Library.html#Library_shared_ptr_templates">shared_ptr and templates</a>
|
||||
<li><a href="Library.html#Library_shared_ptr_directors">shared_ptr and directors</a>
|
||||
</ul>
|
||||
|
|
@ -478,7 +484,7 @@
|
|||
<li><a href="Typemaps.html#Typemaps_nn35">"memberin" typemap</a>
|
||||
<li><a href="Typemaps.html#Typemaps_nn36">"varin" typemap</a>
|
||||
<li><a href="Typemaps.html#Typemaps_nn37">"varout" typemap</a>
|
||||
<li><a href="Typemaps.html#throws_typemap">"throws" typemap</a>
|
||||
<li><a href="Typemaps.html#Typemaps_throws_typemap">"throws" typemap</a>
|
||||
</ul>
|
||||
<li><a href="Typemaps.html#Typemaps_nn39">Some typemap examples</a>
|
||||
<ul>
|
||||
|
|
@ -500,6 +506,9 @@
|
|||
<li><a href="Typemaps.html#Typemaps_runtime_type_checker_usage">Usage</a>
|
||||
</ul>
|
||||
<li><a href="Typemaps.html#Typemaps_overloading">Typemaps and overloading</a>
|
||||
<ul>
|
||||
<li><a href="Typemaps.html#Typemaps_typecheck_pointer">SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap</a>
|
||||
</ul>
|
||||
<li><a href="Typemaps.html#Typemaps_nn48">More about %apply and %clear</a>
|
||||
<li><a href="Typemaps.html#Typemaps_nn47">Passing data between typemaps</a>
|
||||
<li><a href="Typemaps.html#Typemaps_nn52">C++ "this" pointer</a>
|
||||
|
|
@ -1027,6 +1036,9 @@
|
|||
<li><a href="Java.html#Java_directors_threading">Director threading issues</a>
|
||||
<li><a href="Java.html#Java_directors_performance">Director performance tuning</a>
|
||||
<li><a href="Java.html#Java_exceptions_from_directors">Java exceptions from directors</a>
|
||||
<ul>
|
||||
<li><a href="Java.html#Java_customizing_director_exceptions">Customizing director exceptions</a>
|
||||
</ul>
|
||||
</ul>
|
||||
<li><a href="Java.html#Java_allprotected">Accessing protected members</a>
|
||||
<li><a href="Java.html#Java_common_customization">Common customization features</a>
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@
|
|||
<li><a href="#Java_directors_threading">Director threading issues</a>
|
||||
<li><a href="#Java_directors_performance">Director performance tuning</a>
|
||||
<li><a href="#Java_exceptions_from_directors">Java exceptions from directors</a>
|
||||
<ul>
|
||||
<li><a href="#Java_customizing_director_exceptions">Customizing director exceptions</a>
|
||||
</ul>
|
||||
</ul>
|
||||
<li><a href="#Java_allprotected">Accessing protected members</a>
|
||||
<li><a href="#Java_common_customization">Common customization features</a>
|
||||
|
|
@ -3746,12 +3749,10 @@ Naturally, the SWIG generated C++ code and the generated Java intermediary class
|
|||
|
||||
<div class="code">
|
||||
<pre>
|
||||
public class DirectorDerived extends DirectorBase {
|
||||
public DirectorDerived() {
|
||||
}
|
||||
|
||||
class DirectorDerived extends DirectorBase {
|
||||
@Override
|
||||
public void upcall_method() {
|
||||
System.out.println("DirectorDerived::upcall_method() invoked.");
|
||||
System.out.println("DirectorDerived.upcall_method() invoked.");
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
|
@ -3774,7 +3775,7 @@ will result in the following being output:
|
|||
|
||||
<div class="code">
|
||||
<pre>
|
||||
DirectorDerived::upcall_method() invoked.
|
||||
DirectorDerived.upcall_method() invoked.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
|
@ -3825,45 +3826,186 @@ The disadvantage is that invocation of director methods from C++ when Java doesn
|
|||
<p>
|
||||
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
|
||||
<code>DirectorException</code> 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 store the thrown Java exception into a SWIG defined
|
||||
<code>Swig::DirectorException</code> C++ class exception in the C++ layer and then throw this C++ exception.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Converting Java exceptions into C++ exceptions can be done in two different ways using
|
||||
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.
|
||||
Of course, should this exception be thrown, your C++ code must catch it and handle it before returning back to Java.
|
||||
The default generated code <b>does not</b> attempt to handle the C++ exception, but there is a simple way
|
||||
to make this all work by catching the C++ exception and extracting the original Java exception by using <tt>%catches</tt> for <tt>Swig::DirectorException</tt>.
|
||||
Consider the example shown earlier with a modification to the <tt>upcall_method</tt> Java method to throw a Java exception:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%feature("director:except") MyClass::method(int x) {
|
||||
jthrowable $error = jenv->ExceptionOccurred();
|
||||
if ($error) {
|
||||
jenv->ExceptionClear();
|
||||
if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException"))
|
||||
throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||
if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyJavaException"))
|
||||
throw MyCppException(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||
throw std::runtime_error("Unexpected exception thrown in MyClass::method");
|
||||
class DirectorDerived extends DirectorBase {
|
||||
@Override
|
||||
public void upcall_method() {
|
||||
System.out.println("DirectorDerived.upcall_method() invoked.");
|
||||
throw new RuntimeException("There was a problem!");
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
/** Throws either a std::out_of_range or MyCppException on error */
|
||||
void method(int x);
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This approach allows a flexible mapping of Java exceptions thrown by director methods into
|
||||
C++ exceptions expected by a C++ caller. There
|
||||
need not be any C++ <em>exception specifications</em> on the C++ method. The
|
||||
utility function <code>Swig::ExceptionMatches</code>
|
||||
Now, by default, the JVM will abort when <tt>example.callup(director)</tt> is called as the C++
|
||||
<tt>Swig::DirectorException</tt> (storing the Java exception) is thrown and not handled by the <tt>callup</tt> method.
|
||||
Needless to say this is not very user friendly and so the recommendation is to add the following
|
||||
simple <tt>%catches</tt> directive before SWIG parses the <tt>callup</tt> function:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%catches(Swig::DirectorException) callup;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Or target all wrapped methods using:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%catches(Swig::DirectorException);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This tells SWIG to generate a C++ catch handler using some code from the <a href="Typemaps.html#Typemaps_throws_typemap">throws typemap</a> for <tt>Swig::DirectorException</tt> that SWIG supplies by default, see <a href="SWIGPlus.html#SWIGPlus_catches">Exception handling with %catches</a>.
|
||||
This typemap code is written to simply catch the C++ <tt>Swig::DirectorException</tt> class and immediately
|
||||
return to Java throwing the original Java exception that it has stored.
|
||||
The net result is a stack trace containing the original Java exception including the location that the exception was thown from.
|
||||
</p>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
DirectorDerived.upcall_method() invoked.
|
||||
Exception in thread "main" java.lang.RuntimeException: There was a problem!
|
||||
at DirectorDerived.upcall_method(runme.java:4)
|
||||
at exampleJNI.SwigDirector_DirectorBase_upcall_method(exampleJNI.java:20)
|
||||
at exampleJNI.callup(Native Method)
|
||||
at example.callup(example.java:12)
|
||||
at runme.main(runme.java:21)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
More on the <tt>Swig::DirectorException</tt> class can be found in the next section which details how to customize the handling of director exceptions.
|
||||
</p>
|
||||
|
||||
<H4><a name="Java_customizing_director_exceptions">25.5.7.1 Customizing director exceptions</a></H4>
|
||||
|
||||
|
||||
<p>
|
||||
This section is for advanced customization of director exceptions.
|
||||
The recommendation for most users is to use the simple <tt>%catches</tt> directive described above as it should be sufficient for most users needs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The conversion of Java exceptions into C++ exceptions can be customized in two different ways using
|
||||
the <code>director:except</code> <a href="Customization.html#Customization_features">feature</a>.
|
||||
In the first approach, a code block is attached to each director method to
|
||||
handle the mapping of Java exceptions into C++ exceptions.
|
||||
The code block is generated just after the call up from the C++ director method into the overloaded method in Java. Its primary function is to check if a Java exception has been thrown and then handle it in C++.
|
||||
The example below converts a
|
||||
<tt>java.lang.IndexOutOfBoundsException</tt> into a C++ <tt>std::out_of_range</tt> exception and converts a
|
||||
user's Java <tt>MyJavaException</tt> into a C++ <tt>MyCppException</tt> exception.
|
||||
If the Java exception doesn't match either of these, a fallback <tt>std::runtime_error</tt> C++ exception is thrown.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%feature("director:except") MyClass::dirmethod(int x) {
|
||||
jthrowable $error = jenv->ExceptionOccurred();
|
||||
if ($error) {
|
||||
if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException"))
|
||||
throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||
if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyJavaException"))
|
||||
throw MyCppException(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||
throw std::runtime_error("Unexpected exception thrown in MyClass::dirmethod");
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
public:
|
||||
/** Throws either a std::out_of_range or MyCppException on error */
|
||||
virtual void dirmethod(int x);
|
||||
virtual ~MyClass();
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
A few special variables are expanded within the <tt>director:except</tt> feature.
|
||||
</p>
|
||||
<ul>
|
||||
<li> The special variable <tt>$error</tt> is expanded into a unique variable name (swigerror)
|
||||
and should be used for the assignment of the jthrowable exception that occurred.</li>
|
||||
<li> The special variable <tt>$packagepath</tt> is
|
||||
replaced by the outer package provided for SWIG generation by the -package option. </li>
|
||||
<li> The special variable <tt>$directorthrowshandlers</tt> is not shown above, but is replaced
|
||||
by applicable "directorthrows" typemap contents (covered later in this section). </li>
|
||||
<li> The special variable <tt>$null</tt> is not shown above, but is replaced
|
||||
by a suitable default constructed object for returning from the director method (or nothing if
|
||||
the director method has a void return).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Utility functions/classes in director.swg are provided to aid the exception conversion as follows:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
namespace Swig {
|
||||
|
||||
// Helper method to determine if a Java throwable matches a particular Java class type
|
||||
// Note side effect of clearing any pending exceptions
|
||||
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 throwException(JNIEnv *jenv) const;
|
||||
|
||||
// Create and throw the DirectorException
|
||||
static void raise(JNIEnv *jenv, jthrowable throwable) {
|
||||
throw DirectorException(jenv, throwable);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The utility function <code>Swig::ExceptionMatches</code>
|
||||
and class <code>Swig::JavaExceptionMessage</code> are provided to simplify
|
||||
writing code for wrappers that use the <code>director:except</code> feature. The
|
||||
function <code>Swig::ExceptionMatches</code> matches the type of the
|
||||
|
|
@ -3871,13 +4013,10 @@ function <code>Swig::ExceptionMatches</code> matches the type of the
|
|||
name, such as <code>"java/lang/IOError"</code>. If the throwable class is the same
|
||||
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
|
||||
generated proxy class will have additional package qualification, depending on
|
||||
generated proxy class will have an additional package qualification, depending on
|
||||
the '-package' argument and use of the <a href="#Java_namespaces">nspace
|
||||
feature</a>. The special variable <code>$error</code> is expanded by SWIG into a unique variable name and
|
||||
should be used for the
|
||||
assignment of the exception that occurred. The special variable <code>$packagepath</code> is
|
||||
replaced by the outer package provided for SWIG generation by the -package
|
||||
option. The utility class <code>Swig::JavaExceptionMessage</code> is a holder
|
||||
feature</a>.
|
||||
The utility class <code>Swig::JavaExceptionMessage</code> is a holder
|
||||
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
|
||||
|
|
@ -3885,20 +4024,27 @@ needs to copy it, for example into a std::string or a newly constructed C++ exce
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Using the above approach to
|
||||
Using the first approach above to
|
||||
write handlers for a large number of methods will require
|
||||
repetitive duplication of the <code>director:except</code> feature code.
|
||||
To mitigate this, an alternative approach is provided via typemaps in a
|
||||
repetitive duplication of the <code>director:except</code> feature code
|
||||
for each director method.
|
||||
To mitigate this, a second approach is provided via typemaps in a
|
||||
fashion analagous to
|
||||
the <a href="Typemaps.html#throws_typemap">"throws" typemap.</a> The
|
||||
"throws" typemap provides an approach to automatically map all the C++
|
||||
the <a href="Typemaps.html#throws_typemap">"throws" typemap</a>.
|
||||
The "throws" typemap provides a way to map all the C++
|
||||
exceptions listed in a method's defined exceptions (either from
|
||||
a C++ <em>exception specification</em> or a <code>%catches</code>
|
||||
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.
|
||||
Only use this typemap if you wish to write custom conversions of Java exceptions into C++ exceptions
|
||||
and apply them to many different methods.
|
||||
The default handling which uses the <code>Swig::DirectorException</code> class should otherwise meet your needs.
|
||||
</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>:
|
||||
to the typemap's type, that is a <code>std::out_of_range</code> C++ exception:
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
|
|
@ -3913,7 +4059,7 @@ to the typemap's type, that is <code>std::out_of_range</code>:
|
|||
<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:
|
||||
is used in the code block. Consider the following, which also happens to be the default:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -3921,7 +4067,6 @@ is used in the feature code. Consider the following, which also happens to be th
|
|||
%feature("director:except") %{
|
||||
jthrowable $error = jenv->ExceptionOccurred();
|
||||
if ($error) {
|
||||
jenv->ExceptionClear();
|
||||
$directorthrowshandlers
|
||||
Swig::DirectorException::raise(jenv, $error);
|
||||
}
|
||||
|
|
@ -3930,34 +4075,33 @@ is used in the feature code. Consider the following, which also happens to be th
|
|||
</div>
|
||||
|
||||
<p>
|
||||
where <tt>Swig::DirectorException::raise</tt> is a helper method in the DirectorException class to throw a C++ exception (implemented in director.swg):
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
static void raise(JNIEnv *jenv, jthrowable throwable) {
|
||||
throw DirectorException(jenv, throwable);
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>The code generated using the <code>director:except</code> feature
|
||||
replaces the <code>$directorthrowshandlers</code> special variable with the code in
|
||||
the "directorthrows" typemaps, for each and every exception defined for the method.
|
||||
The possible exceptions can be defined either with a C++ exception
|
||||
where <tt>Swig::DirectorException::raise</tt> is the helper method to throw a C++ <tt>Swig::DirectorException</tt>, see above.
|
||||
The code generated from the <code>director:except</code> feature
|
||||
has the <code>$directorthrowshandlers</code> special variable replaced with the code in
|
||||
the relevant "directorthrows" typemaps, for each and every exception defined for the method.
|
||||
The relevant exceptions can be defined either with a C++ exception
|
||||
specification or <code>%catches</code> as described for the
|
||||
<a href="Typemaps.html#throws_typemap">"throws" typemap</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Consider the following director method:
|
||||
Let's try and put all this together by considering the following director method:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
...
|
||||
struct X {
|
||||
virtual void doSomething(int index) throw (std::out_of_range);
|
||||
...
|
||||
};
|
||||
|
||||
OR
|
||||
|
||||
%catches(std::out_of_range) X::doSomething;
|
||||
struct X {
|
||||
virtual void doSomething(int index);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
|
@ -3970,11 +4114,9 @@ the resulting code generated in the director method after calling up to Java wil
|
|||
<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());
|
||||
}
|
||||
|
||||
Swig::DirectorException::raise(jenv, swigerror);
|
||||
}
|
||||
</pre>
|
||||
|
|
@ -3983,7 +4125,7 @@ if (swigerror) {
|
|||
<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
|
||||
director method throws an exception that is not specified in the exception specifications list 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.
|
||||
|
|
@ -3991,8 +4133,9 @@ this potential fate.
|
|||
|
||||
<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:
|
||||
specifications may cause program termination as this exception class won't be in the exception specifications list.
|
||||
You can avoid throwing <tt>Swig::DirectorException</tt> by changing the default handling for all methods by adding a <tt>director:except</tt> feature without any method name.
|
||||
For example, you can just ignore them:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -4000,8 +4143,8 @@ unexpected exceptions, the default handling can be changed with:
|
|||
%feature("director:except") %{
|
||||
jthrowable $error = jenv->ExceptionOccurred();
|
||||
if ($error) {
|
||||
jenv->ExceptionClear();
|
||||
$directorthrowshandlers
|
||||
jenv->ExceptionClear();
|
||||
return $null; // exception is ignored
|
||||
}
|
||||
%}
|
||||
|
|
@ -4011,7 +4154,7 @@ unexpected exceptions, the default handling can be changed with:
|
|||
<p>Alternatively an exception compatible with the existing director
|
||||
method exception specifications can be thrown. Assuming that all
|
||||
methods allow std::runtime_error to be thrown,
|
||||
the <code>return $null;</code> could be changed to:
|
||||
the <code>return $null</code> line above could be changed to:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -4021,124 +4164,296 @@ the <code>return $null;</code> could be changed to:
|
|||
</div>
|
||||
|
||||
<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 by providing a method name to the <tt>director:except</tt> feature.
|
||||
</p>
|
||||
|
||||
<p>Below is a complete example demonstrating the use
|
||||
of the "directorthrows" typemaps. In this example, a
|
||||
generic "directorthrows" typemap is appropriate for all three exceptions - all
|
||||
take single string constructors. If the exceptions had different constructors,
|
||||
it would be necessary to have separate typemaps for each exception type.
|
||||
<p>This is all no doubt quite hard to follow without seeing a full example and some code.
|
||||
Below is a complete example demonstrating the use
|
||||
of most of the exception customizations one can use, that is,
|
||||
"directorthrows" and "throws" typemaps, %exception and %catches.
|
||||
See the <a href="#Java_exception_handling">Exception handling with %exception and %javaexception</a>
|
||||
section for more on converting C++ exceptions to Java exceptions.
|
||||
The example also has a user defined C++ exception class called <tt>MyNS::MyException</tt> and this is wrapped as a Java exception.
|
||||
The director class being wrapped is <tt>MyClass</tt> and the director method is called <tt>MyClass::dirmethod</tt>.
|
||||
A number of <tt>std::cout</tt> calls have been added to help understand code flow.
|
||||
You can copy the code below into an interface file and run SWIG on it and examine the generated code.
|
||||
|
||||
|
||||
<!-- All the DEFINE_ and DECLARE_EXCEPTIONS CAN BE OMITTED to make
|
||||
this more succinct. They are included to make this a complete
|
||||
example interface that could be generated and built. -->
|
||||
<div class="code">
|
||||
<pre>
|
||||
%module(directors="1") example
|
||||
|
||||
%{
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
%}
|
||||
|
||||
// Define exceptions in header section using std::runtime_error
|
||||
%define DEFINE_EXCEPTION(NAME)
|
||||
%{
|
||||
namespace MyNS {
|
||||
struct NAME : public std::runtime_error { NAME(const std::string &what) : runtime_error(what) {} };
|
||||
// Generic catch handler for all wrapped methods
|
||||
%exception %{
|
||||
try {
|
||||
$action
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << "Generic std::exception catch handler" << std::endl;
|
||||
jclass clazz = jenv->FindClass("java/lang/RuntimeException");
|
||||
jenv->ThrowNew(clazz, e.what());
|
||||
return $null;
|
||||
}
|
||||
%}
|
||||
%enddef
|
||||
|
||||
// Expose C++ exceptions as Java Exceptions by changing the Java base class and providing a getMessage()
|
||||
%define DECLARE_EXCEPTION(NAME)
|
||||
%typemap(javabase) MyNS::NAME "java.lang.Exception";
|
||||
%rename(getMessage) MyNS::NAME::what;
|
||||
// Expose C++ exception as a Java Exception by changing the Java base class and providing a getMessage()
|
||||
%typemap(javabase) MyNS::MyException "java.lang.RuntimeException";
|
||||
%rename(getMessage) MyNS::MyException::whatsup;
|
||||
|
||||
%inline %{
|
||||
namespace MyNS {
|
||||
struct NAME {
|
||||
NAME(const std::string& what);
|
||||
const char * what();
|
||||
class MyException {
|
||||
std::string msg;
|
||||
public:
|
||||
MyException(const char *msg) : msg(msg) {}
|
||||
const char * whatsup() const { return msg.c_str(); }
|
||||
};
|
||||
}
|
||||
%enddef
|
||||
|
||||
DEFINE_EXCEPTION(ExceptionA)
|
||||
DEFINE_EXCEPTION(ExceptionB)
|
||||
DEFINE_EXCEPTION(Unexpected)
|
||||
|
||||
// Mark three methods to map director thrown exceptions.
|
||||
%feature("director:except") MyClass::meth1(int);
|
||||
%feature("director:except") MyClass::meth2;
|
||||
%feature("director:except") meth3;
|
||||
|
||||
%typemap(directorthrows) MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected %{
|
||||
if (Swig::ExceptionMatches(jenv, $error, "$packagepath/$javaclassname"))
|
||||
throw $1_type(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||
%}
|
||||
|
||||
DECLARE_EXCEPTION(ExceptionA)
|
||||
DECLARE_EXCEPTION(ExceptionB)
|
||||
DECLARE_EXCEPTION(Unexpected)
|
||||
%typemap(directorthrows) MyNS::MyException %{
|
||||
if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyException")) {
|
||||
std::cout << "$1_type exception matched (directorthrows typemap)" << std::endl;
|
||||
throw $1_type(Swig::JavaExceptionMessage(jenv, $error).message());
|
||||
}
|
||||
%}
|
||||
|
||||
%catches(MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected) MyClass::meth2();
|
||||
%typemap(throws) MyNS::MyException %{
|
||||
std::cout << "$1_type caught (throws typemap)" << std::endl;
|
||||
jclass excep = jenv->FindClass("MyException");
|
||||
if (excep) {
|
||||
std::cout << "$1_type class found (throws typemap)" << std::endl;
|
||||
jenv->ThrowNew(excep, $1.whatsup());
|
||||
}
|
||||
return $null;
|
||||
%}
|
||||
|
||||
%inline {
|
||||
class MyClass {
|
||||
public:
|
||||
virtual void meth1(int x) throw(MyNS::ExceptionA, MyNS::ExceptionB) = 0;
|
||||
virtual void meth2() = 0; /* throws MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected */
|
||||
virtual void meth3(float x) throw(MyNS::Unexpected) = 0;
|
||||
virtual ~MyClass() {}
|
||||
};
|
||||
// These are the exceptions that the director method MyClass::dirmethod will have catch handlers for.
|
||||
// Note that this is also a virtual method / director method and the C++ exceptions listed can be
|
||||
// thrown after converting them from Java exceptions.
|
||||
%catches(MyNS::MyException, Swig::DirectorException) MyClass::dirmethod;
|
||||
|
||||
// These are the exceptions that call_dirmethod C++ wrapper will have catch handlers for.
|
||||
// Note that this is not a virtual method, hence not a director method.
|
||||
%catches(MyNS::MyException, Swig::DirectorException) call_dirmethod;
|
||||
|
||||
%feature("director") MyClass;
|
||||
|
||||
%feature("director:except") MyClass::dirmethod(int x) {
|
||||
jthrowable $error = jenv->ExceptionOccurred();
|
||||
if ($error) {
|
||||
std::cout << "Upcall finished, an exception was thrown in Java" << std::endl;
|
||||
$directorthrowshandlers
|
||||
std::cout << "Upcall finished, no exception conversion, throwing DirectorException" << std::endl;
|
||||
Swig::DirectorException::raise(jenv, $error);
|
||||
}
|
||||
}
|
||||
|
||||
%inline %{
|
||||
class MyClass {
|
||||
public:
|
||||
/** Throws either a std::out_of_range or MyException on error */
|
||||
virtual void dirmethod(int x) {
|
||||
if (x <= 0)
|
||||
throw std::out_of_range("MyClass::dirmethod index is out of range");
|
||||
else if (x == 1)
|
||||
throw MyNS::MyException("MyClass::dirmethod some problem!");
|
||||
}
|
||||
virtual ~MyClass() {}
|
||||
static void call_dirmethod(MyClass& c, int x) {
|
||||
return c.dirmethod(x);
|
||||
}
|
||||
};
|
||||
%}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
In this case the three different "directorthrows" typemaps will be used
|
||||
to generate the three different exception handlers for
|
||||
<code>meth1</code>, <code>meth2</code> and <code>meth3</code>. The generated
|
||||
handlers will have "if" blocks for each exception type specified, in
|
||||
the exception specification or <code>%catches</code> feature.
|
||||
</p>
|
||||
|
||||
<p>Note that the "directorthrows" typemaps are important
|
||||
only if it is important for the exceptions passed through the C++
|
||||
layer to be mapped to distinct C++ exceptions. If director methods
|
||||
are being called by C++ code that is itself wrapped in a
|
||||
SWIG generated Java wrapper and access is always through this wrapper,
|
||||
the default <code>Swig::DirectorException</code> class provides enough information
|
||||
to reconstruct the original exception. In this case removing the
|
||||
<code>$directorthrowshandlers</code> special variable from the
|
||||
default <code>director:except</code> feature and simply always
|
||||
throwing a <code>Swig::DirectorException</code> will achieve the desired result.
|
||||
Along with this a generic exception feature is added to convert any
|
||||
caught <code>Swig::DirectorException</code>s back into the underlying
|
||||
Java exceptions via the <code>Swig::DirectorException::raiseJavaException</code> method,
|
||||
as demonstrated with <code>%javaexception</code> below:
|
||||
The generated code for the <tt>call_dirmethod</tt> wrapper contains the various exception handlers.
|
||||
The outer exception handler is from the <tt>%exception</tt> directive and the others
|
||||
are from the "throws" typemaps.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%javaexception("Exception") MyClass::myMethod %{
|
||||
SWIGEXPORT void JNICALL Java_exampleJNI_MyClass_1call_1dirmethod(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
|
||||
...
|
||||
try {
|
||||
$action
|
||||
} catch (Swig::DirectorException &e) {
|
||||
// raise/throw the Java exception that originally caused the DirectorException
|
||||
e.raiseJavaException(jenv);
|
||||
return $null;
|
||||
try {
|
||||
MyClass::call_dirmethod(*arg1,arg2);
|
||||
} catch(MyNS::MyException &_e) {
|
||||
std::cout << "MyNS::MyException caught (throws typemap)" << std::endl;
|
||||
jclass excep = jenv->FindClass("MyException");
|
||||
if (excep) {
|
||||
std::cout << "MyNS::MyException class found (throws typemap)" << std::endl;
|
||||
jenv->ThrowNew(excep, (&_e)->whatsup());
|
||||
}
|
||||
return ;
|
||||
|
||||
} catch(Swig::DirectorException &_e) {
|
||||
(&_e)->throwException(jenv);
|
||||
return ;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << "Generic std::exception catch handler" << std::endl;
|
||||
jclass clazz = jenv->FindClass("java/lang/RuntimeException");
|
||||
jenv->ThrowNew(clazz, e.what());
|
||||
return ;
|
||||
}
|
||||
%}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
See the <a href="#Java_exception_handling">Exception handling with %exception and %javaexception</a>
|
||||
section for more on converting C++ exceptions to Java exceptions.
|
||||
The director method calling up to Java contains the exception handling code from the "directorthrows" typemaps and <tt>director:except</tt> feature.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
void SwigDirector_MyClass::dirmethod(int x) {
|
||||
... [call up to Java using CallStaticVoidMethod]
|
||||
jthrowable swigerror = jenv->ExceptionOccurred();
|
||||
if (swigerror) {
|
||||
std::cout << "Upcall finished, an exception was thrown in Java" << std::endl;
|
||||
|
||||
if (Swig::ExceptionMatches(jenv, swigerror, "MyException")) {
|
||||
std::cout << "MyNS::MyException exception matched (directorthrows typemap)" << std::endl;
|
||||
throw MyNS::MyException(Swig::JavaExceptionMessage(jenv, swigerror).message());
|
||||
}
|
||||
|
||||
std::cout << "Upcall finished, no exception conversion, throwing DirectorException" << std::endl;
|
||||
Swig::DirectorException::raise(jenv, swigerror);
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Let's use the following Java class to override the director method.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
class DerivedClass extends MyClass {
|
||||
@Override
|
||||
public void dirmethod(int x) {
|
||||
if (x < 0)
|
||||
throw new IndexOutOfBoundsException("Index is negative");
|
||||
else if (x == 0)
|
||||
throw new MyException("MyException: bad dirmethod");
|
||||
}
|
||||
}
|
||||
public class runme {
|
||||
public static void main(String argv[]) {
|
||||
System.loadLibrary("example");
|
||||
... code snippets shown below ...
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Consider the output using the Java code in the four slightly different scenarios below.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
1. Non-director C++ class is used, thus, no upcall to a Java director method is made.
|
||||
A <tt>std::out_of_range</tt> exception is thrown, which is derived from <tt>std::exception</tt>,
|
||||
and hence caught by the generic exception handler in the <tt>call_dirmethod</tt> wrapper.
|
||||
The Java code snippet and resulting output is:
|
||||
</p>
|
||||
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
MyClass.call_dirmethod(new MyClass(), 0);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
Generic std::exception catch handler
|
||||
Exception in thread "main" java.lang.RuntimeException: MyClass::dirmethod index is out of range
|
||||
at exampleJNI.MyClass_call_dirmethod(Native Method)
|
||||
at MyClass.call_dirmethod(MyClass.java:57)
|
||||
at runme.main(runme.java:14)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
2. Non-director C++ class again but this time the <tt>MyNS::MyException</tt> class is thrown and caught:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
MyClass.call_dirmethod(new MyClass(), 1);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
MyNS::MyException caught (throws typemap)
|
||||
MyNS::MyException class found (throws typemap)
|
||||
Exception in thread "main" MyException: MyClass::dirmethod some problem!
|
||||
at exampleJNI.MyClass_call_dirmethod(Native Method)
|
||||
at MyClass.call_dirmethod(MyClass.java:57)
|
||||
at runme.main(runme.java:15)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
3. The <tt>DerivedClass</tt> director class is used so the upcall to Java occurs, but it throws
|
||||
a Java <tt>MyException</tt>, which gets converted into a C++ <tt>MyNS::MyException</tt>, then caught and converted back
|
||||
into a Java <tt>MyException</tt>:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
MyClass.call_dirmethod(new DerivedClass(), 0);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
Upcall finished, an exception was thrown in Java
|
||||
MyNS::MyException exception matched (directorthrows typemap)
|
||||
MyNS::MyException caught (throws typemap)
|
||||
MyNS::MyException class found (throws typemap)
|
||||
Exception in thread "main" MyException: MyException: bad dirmethod
|
||||
at exampleJNI.MyClass_call_dirmethod(Native Method)
|
||||
at MyClass.call_dirmethod(MyClass.java:57)
|
||||
at runme.main(runme.java:16)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
4. The director class is used again, but this time the director method throws a Java <tt>IndexOutOfBoundsException</tt> exception which is converted into a C++ <tt>Swig::DirectorException</tt>, thrown and caught again.
|
||||
This time the original Java exception is extracted from the <tt>Swig::DirectorException</tt> and rethrown.
|
||||
Note that this approach keeps the stack trace information of the original exception, so it has the exact location of where the <tt>IndexOutOfBoundsException</tt> exception was thrown.
|
||||
This is arguably an improvement over the approach above that converts from a Java excepton to C++ exception and then back to a new Java exception, losing the location of the original exception.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
MyClass.call_dirmethod(new DerivedClass(), -1);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
Upcall finished, an exception was thrown in Java
|
||||
Upcall finished, no exception conversion, throwing DirectorException
|
||||
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index is negative
|
||||
at DerivedClass.dirmethod(runme.java:5)
|
||||
at exampleJNI.SwigDirector_MyClass_dirmethod(exampleJNI.java:23)
|
||||
at exampleJNI.MyClass_call_dirmethod(Native Method)
|
||||
at MyClass.call_dirmethod(MyClass.java:57)
|
||||
at runme.main(runme.java:17)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<H2><a name="Java_allprotected">25.6 Accessing protected members</a></H2>
|
||||
|
||||
|
||||
|
|
@ -8165,40 +8480,52 @@ public class Container {
|
|||
// Ensure that the GC doesn't collect any Element set from Java
|
||||
// as the underlying C++ class stores a shallow copy
|
||||
private Element elementReference;
|
||||
private long getCPtrAndAddReference(Element element) {
|
||||
elementReference = element;
|
||||
return Element.getCPtr(element);
|
||||
}
|
||||
|
||||
public void setElement(Element e) {
|
||||
exampleJNI.Container_setElement(swigCPtr, this, getCPtrAndAddReference(e), e);
|
||||
exampleJNI.Container_setElement(swigCPtr, this, Element.getCPtr(e), e);
|
||||
elementReference = e;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The following typemaps will generate the desired code.
|
||||
The 'javain' typemap matches the input parameter type for the <tt>setElement</tt> method.
|
||||
The 'javacode' typemap simply adds in the specified code into the Java proxy class.
|
||||
The following typemaps can be used to generate this code:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%typemap(javain) Element *e "getCPtrAndAddReference($javainput)"
|
||||
|
||||
%typemap(javacode) Container %{
|
||||
// Ensure that the GC doesn't collect any element set from Java
|
||||
// as the underlying C++ class stores a shallow copy
|
||||
private Element elementReference;
|
||||
private long getCPtrAndAddReference(Element element) {
|
||||
elementReference = element;
|
||||
return Element.getCPtr(element);
|
||||
}
|
||||
%}
|
||||
|
||||
%typemap(javain,
|
||||
post=" elementReference = $javainput;"
|
||||
) Element *e "Element.getCPtr($javainput)"
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The 'javacode' typemap simply adds in the specified code into the Java proxy class.
|
||||
The 'javain' typemap matches the input parameter type and name for the <tt>setElement</tt> method and
|
||||
the 'post' typemap attribute allows adding code after the JNI call.
|
||||
The 'post' code is generated into a finally block after the JNI call so the resulting code isn't quite
|
||||
as mentioned earlier, <tt>setElement</tt> is actually:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
public void setElement(Element e) {
|
||||
try {
|
||||
exampleJNI.Container_setElement(swigCPtr, this, Element.getCPtr(e), e);
|
||||
} finally {
|
||||
elementReference = e;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="Java_date_marshalling">25.10.13 Date marshalling using the javain typemap and associated attributes</a></H3>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
<ul>
|
||||
<li><a href="#Library_shared_ptr_basics">shared_ptr basics</a>
|
||||
<li><a href="#Library_shared_ptr_inheritance">shared_ptr and inheritance</a>
|
||||
<li><a href="#Library_shared_ptr_overloading">shared_ptr and method overloading</a>
|
||||
<li><a href="#Library_shared_ptr_templates">shared_ptr and templates</a>
|
||||
<li><a href="#Library_shared_ptr_directors">shared_ptr and directors</a>
|
||||
</ul>
|
||||
|
|
@ -419,11 +420,11 @@ Now, in a scripting language, you might write this:
|
|||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
a = new_doubleArray(10) # Create an array
|
||||
a = new_doubleArray(10) # Create an array
|
||||
for i in range(0, 10):
|
||||
doubleArray_setitem(a, i, 2*i) # Set a value
|
||||
print_array(a) # Pass to C
|
||||
delete_doubleArray(a) # Destroy array
|
||||
doubleArray_setitem(a, i, 2 * i) # Set a value
|
||||
print_array(a) # Pass to C
|
||||
delete_doubleArray(a) # Destroy array
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
|
@ -486,7 +487,7 @@ Allows you to do this:
|
|||
import example
|
||||
c = example.doubleArray(10) # Create double[10]
|
||||
for i in range(0, 10):
|
||||
c[i] = 2*i # Assign values
|
||||
c[i] = 2 * i # Assign values
|
||||
example.print_array(c) # Pass to C
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -502,6 +503,7 @@ you should consider using a special array object rather than a bare pointer.
|
|||
<p>
|
||||
<b>Note:</b> <tt>%array_functions()</tt> and <tt>%array_class()</tt> should not be
|
||||
used with types of <tt>char</tt> or <tt>char *</tt>.
|
||||
SWIG's default handling of these types is to handle them as character strings and the two macros do not do enough to change this.
|
||||
</p>
|
||||
|
||||
<H3><a name="Library_nn6">9.2.3 cmalloc.i</a></H3>
|
||||
|
|
@ -1474,7 +1476,7 @@ In the target language:
|
|||
<div class="targetlang">
|
||||
<pre>
|
||||
x = my_struct();
|
||||
x.foo="Hello World"; # assign with string
|
||||
x.foo = "Hello World"; # assign with string
|
||||
print x.foo; # print as string
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -1921,7 +1923,30 @@ Adding the missing <tt>%shared_ptr</tt> macros will fix this:
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H4><a name="Library_shared_ptr_templates">9.4.4.3 shared_ptr and templates</a></H4>
|
||||
<H4><a name="Library_shared_ptr_overloading">9.4.4.3 shared_ptr and method overloading</a></H4>
|
||||
|
||||
|
||||
<p>
|
||||
A C++ compiler can disambiguate a method overloaded by a shared_ptr and one using the raw underlying type.
|
||||
For example, either one of these methods can be called in C++:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
int age(std::shared_ptr<GrandParent> num);
|
||||
int age(GrandParent& num);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
When wrapped by SWIG, disambiguation is not possible using the overloaded names as there is just one equivalent type (<tt>GrandParent</tt>) in the target language.
|
||||
SWIG will choose to wrap just the first method by default.
|
||||
<a href="SWIGPlus.html#SWIGPlus_nn25">Ambiguity in overloading</a> discusses ways to control which method(s) gets wrapped using <tt>%ignore</tt> or <tt>%rename</tt>.
|
||||
For the interested reader, SWIG detects that they are equivalent types via the <a href=Typemaps.html#Typemaps_typecheck_pointer>typecheck typemaps</a> in the shared_ptr library.
|
||||
</p>
|
||||
|
||||
<H4><a name="Library_shared_ptr_templates">9.4.4.4 shared_ptr and templates</a></H4>
|
||||
|
||||
|
||||
<p>
|
||||
The <tt>%shared_ptr</tt> macro should be used for all the required instantiations
|
||||
|
|
@ -1962,13 +1987,11 @@ The SWIG code below shows the required ordering:
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H4><a name="Library_shared_ptr_directors">9.4.4.4 shared_ptr and directors</a></H4>
|
||||
<H4><a name="Library_shared_ptr_directors">9.4.4.5 shared_ptr and directors</a></H4>
|
||||
|
||||
|
||||
<p>
|
||||
There is somewhat limited support for <tt>%shared_ptr</tt> and the director feature
|
||||
and the degrees of success varies among the different target languages.
|
||||
Please help to improve this support by providing patches with improvements.
|
||||
The languages that support shared_ptr also have support for using shared_ptr with directors.
|
||||
</p>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6521,14 +6521,16 @@ string that cannot be completely decoded as UTF-8:
|
|||
<div class="code"><pre>
|
||||
%module example
|
||||
|
||||
%include <std_string.i>
|
||||
|
||||
%inline %{
|
||||
|
||||
const char* non_utf8_c_str(void) {
|
||||
const char * non_utf8_c_str(void) {
|
||||
return "h\xe9llo w\xc3\xb6rld";
|
||||
}
|
||||
|
||||
void instring(const char *s) {
|
||||
...
|
||||
}
|
||||
|
||||
%}
|
||||
</pre></div>
|
||||
|
||||
|
|
@ -6590,6 +6592,20 @@ For more details about the <tt>surrogateescape</tt> error handler, please see
|
|||
<a href="https://www.python.org/dev/peps/pep-0383/">PEP 383</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When Python 3 strings are passed to the C/C++ layer, they are expected to be valid UTF8 Unicode strings too.
|
||||
For example, when the <tt>instring</tt> method above is wrapped and called, any invalid UTF8 Unicode code strings
|
||||
will result in a TypeError because the attempted conversion fails:
|
||||
</p>
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
>>> example.instring('h\xe9llo')
|
||||
>>> example.instring('h\udce9llo')
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
TypeError: in method 'instring', argument 1 of type 'char const *'
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
In some cases, users may wish to instead handle all byte strings as bytes
|
||||
objects in Python 3. This can be accomplished by adding
|
||||
|
|
|
|||
|
|
@ -3343,7 +3343,7 @@ SWIG_From_float(float)</td>
|
|||
|
||||
|
||||
<p>Here, while the Ruby versions return the value directly, the SWIG
|
||||
versions do not, but return a status value to indicate success (<tt>SWIG_OK</tt>). While more akward to use, this allows you to write typemaps that report more helpful error messages, like:</p>
|
||||
versions do not, but return a status value to indicate success (<tt>SWIG_OK</tt>). While more awkward to use, this allows you to write typemaps that report more helpful error messages, like:</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
|
|
|
|||
|
|
@ -163,6 +163,32 @@ can be obtained by typing <tt>swig -help</tt> or <tt>swig
|
|||
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
Arguments may also be passed in a command-line options file (also known as a
|
||||
response file) which is useful if they exceed the system command line length
|
||||
limit. To do this, put the arguments in a file, then provide the file name
|
||||
prefixed with <tt>@</tt> like so:
|
||||
</p>
|
||||
|
||||
<div class="shell"><pre>
|
||||
swig @<em>file</em>
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The options read from the file are inserted in place of the file option. If the
|
||||
file does not exist, or cannot be read, then the option will be treated
|
||||
literally and not removed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Options in the file are separated by whitespace. A whitespace character may be
|
||||
included in an option by surrounding the entire option in either single or
|
||||
double quotes. Any character (including a backslash) may be included by
|
||||
prefixing the character to be included with a backslash. The file may itself
|
||||
contain additional <tt>@file</tt> options; any such options will be processed
|
||||
recursively.
|
||||
</p>
|
||||
|
||||
<H3><a name="SWIG_nn3">5.1.1 Input format</a></H3>
|
||||
|
||||
|
||||
|
|
@ -2177,7 +2203,7 @@ in the C++ chapter for further details.
|
|||
<p>
|
||||
Occasionally, a C library may include functions that expect to receive
|
||||
pointers to functions--possibly to serve as callbacks. SWIG
|
||||
provides full support for function pointers provided that the callback
|
||||
provides full support for function pointers when the callback
|
||||
functions are defined in C and not in the target language. For example,
|
||||
consider a function like this:
|
||||
</p>
|
||||
|
|
@ -2321,7 +2347,9 @@ And now, a final note about function pointer support. Although SWIG
|
|||
does not normally allow callback functions to be written in the target language, this
|
||||
can be accomplished with the use of typemaps and other advanced SWIG features.
|
||||
See the <a href="Typemaps.html#Typemaps">Typemaps chapter</a> for more about typemaps
|
||||
and individual target language chapters for more on callbacks and the 'director' feature.
|
||||
and individual target language chapters for more on callbacks.
|
||||
The 'director' feature can be used to make callbacks from C/C++ into the target language,
|
||||
see <a href="SWIGPlus.html#SWIGPlus_target_language_callbacks">Callbacks to the target language</a>.
|
||||
</p>
|
||||
|
||||
<H2><a name="SWIG_nn31">5.5 Structures and unions</a></H2>
|
||||
|
|
|
|||
|
|
@ -72,6 +72,11 @@
|
|||
<li><a href="#SWIGPlus_nn35">Using declarations and inheritance</a>
|
||||
<li><a href="#SWIGPlus_nested_classes">Nested classes</a>
|
||||
<li><a href="#SWIGPlus_const">A brief rant about const-correctness</a>
|
||||
<li><a href="#SWIGPlus_target_language_callbacks">Callbacks to the target language</a>
|
||||
<ul>
|
||||
<li><a href="#SWIGPlus_director_classes_introduction">Introduction to director classes</a>
|
||||
<li><a href="#SWIGPlus_directors_for_function_pointers">Using directors and target language callbacks</a>
|
||||
</ul>
|
||||
<li><a href="#SWIGPlus_nn42">Where to go for more information</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -80,7 +85,10 @@
|
|||
|
||||
|
||||
<p>
|
||||
This chapter describes SWIG's support for wrapping C++. As a prerequisite,
|
||||
This chapter describes SWIG's support for wrapping C++.
|
||||
It is mostly concerned about C++ as defined by the C++ 98 and 03 standards.
|
||||
For C++ 11 features please read the <a href="CPlusPlus11.html">SWIG and C++11</a> chapter.
|
||||
As a prerequisite,
|
||||
you should first read the chapter <a href="SWIG.html#SWIG">SWIG Basics</a> to see
|
||||
how SWIG wraps ANSI C. Support for C++ builds upon ANSI C
|
||||
wrapping and that material will be useful in understanding this chapter.
|
||||
|
|
@ -3144,7 +3152,7 @@ redundant and will simply result in code bloat).
|
|||
</p>
|
||||
|
||||
<p>
|
||||
The template provide to <tt>%template</tt> for instantiation must be the actual template and not a typedef to a template.
|
||||
The template provided to <tt>%template</tt> for instantiation must be the actual template and not a typedef to a template.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -4622,7 +4630,7 @@ The next section details a way of simulating an exception specification or repla
|
|||
Exceptions are automatically handled for methods with an exception specification.
|
||||
Similar handling can be achieved for methods without exception specifications through the <tt>%catches</tt> feature.
|
||||
It is also possible to replace any declared exception specification using the <tt>%catches</tt> feature.
|
||||
In fact, <tt>%catches</tt> uses the same <a href="Typemaps.html#throws_typemap">"throws" typemaps</a> that SWIG uses for exception specifications in handling exceptions.
|
||||
In fact, <tt>%catches</tt> uses the same <a href="Typemaps.html#Typemaps_throws_typemap">"throws" typemaps</a> that SWIG uses for exception specifications in handling exceptions.
|
||||
The <tt>%catches</tt> feature must contain a list of possible types that can be thrown.
|
||||
For each type that is in the list, SWIG will generate a catch handler, in the same way that it would for types declared in the exception specification.
|
||||
Note that the list can also include the catch all specification "...".
|
||||
|
|
@ -5385,7 +5393,152 @@ using another tool if maintaining constness is the most important part
|
|||
of your project.
|
||||
</p>
|
||||
|
||||
<H2><a name="SWIGPlus_nn42">6.29 Where to go for more information</a></H2>
|
||||
<H2><a name="SWIGPlus_target_language_callbacks">6.29 Callbacks to the target language</a></H2>
|
||||
|
||||
|
||||
<p>
|
||||
C/C++ function pointers are often used for callbacks and this is discussed in the
|
||||
<a href="SWIG.html#SWIG_nn30">Pointers to functions and callbacks</a> section.
|
||||
The callback techniques described therein provide a way to control callbacks to a C/C++ function but not callbacks into the target language.
|
||||
The techniques described below show how the director feature can be used to support callbacks from C/C++ to the target language.
|
||||
</p>
|
||||
|
||||
<H3><a name="SWIGPlus_director_classes_introduction">6.29.1 Introduction to director classes</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
The director feature enables the ability for a target language class to derive from a wrapped C++ class.
|
||||
The target language can override virtual methods of a wrapped C++ class, thereby supporting cross-language polymorphism.
|
||||
Code can 'call up' from C++ into the target language by simply calling a virtual method overridden in a derived class in the target language.
|
||||
The wrapped C++ classes that have this ability are termed 'director' classes.
|
||||
The director feature is documented individually in each target language and the reader should locate and read this to obtain a full understanding of directors.
|
||||
</p>
|
||||
|
||||
<H3><a name="SWIGPlus_directors_for_function_pointers">6.29.2 Using directors and target language callbacks</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
SWIG's primary goal is to make it possible to call C/C++ code from a target language, however, the director feature enables the reverse.
|
||||
While there isn't simple direct support for calling target language code from C, the director feature makes this possible.
|
||||
It does require some work and additional wrapper code to be provided by the user.
|
||||
The additional code required must be C++ and not C code and hence may introduce a small dependency on C++ if using a pure C project.
|
||||
In a nutshell, the user must create a C++ base class and turn it into a director class.
|
||||
A virtual method in the director base class is required.
|
||||
SWIG generates the code to call up into the target language when wrapping the director virtual method.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's look at some details next.
|
||||
Consider the same function pointer for a callback called <tt>binary_op</tt> from the
|
||||
<a href="SWIG.html#SWIG_nn30">Pointers to functions and callbacks</a> section.
|
||||
For completeness, the code required for the module and director feature is also shown:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
%module(directors="1") example
|
||||
|
||||
%{
|
||||
int binary_op(int a, int b, int (*op)(int, int)) {
|
||||
return op(a, b);
|
||||
}
|
||||
%}
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The goal is to have a target language function that gets called by <tt>binary_op</tt>.
|
||||
The target language function should have the equivalent signature as the C/C++ function pointer <tt>int (*op)(int, int)</tt>.
|
||||
As we are using directors, we need a C++ virtual method with this signature, so let's
|
||||
define the C++ class and pure virtual method first and make it a director class via the
|
||||
director feature:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
%feature("director") BinaryOp;
|
||||
|
||||
%inline %{
|
||||
struct BinaryOp {
|
||||
virtual int handle(int a, int b) = 0;
|
||||
virtual ~BinaryOp() {}
|
||||
};
|
||||
%}
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The following <tt>handler_helper</tt> function and <tt>binary_op_wrapper</tt> function completes the code needed in the
|
||||
C++/SWIG layer. The <tt>binary_op_wrapper</tt> function is wrapped by SWIG and is very similar to the <tt>binary_op</tt> function,
|
||||
however, it takes a pointer to the director base class <tt>BinaryOp</tt> instead of a C/C++ function pointer.
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
%{
|
||||
static BinaryOp *handler_ptr = NULL;
|
||||
static int handler_helper(int a, int b) {
|
||||
// Make the call up to the target language when handler_ptr
|
||||
// is an instance of a target language director class
|
||||
return handler_ptr->handle(a, b);
|
||||
}
|
||||
// If desired, handler_ptr above could be changed to a thread-local variable in order to make thread-safe
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
int binary_op_wrapper(int a, int b, BinaryOp *handler) {
|
||||
handler_ptr = handler;
|
||||
int result = binary_op(a, b, &handler_helper);
|
||||
handler = NULL;
|
||||
return result;
|
||||
}
|
||||
%}
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
On the target language side, we need to derive a class from <tt>BinaryOp</tt> and override the
|
||||
<tt>handle</tt> method. In Python this could be as simple as:
|
||||
</p>
|
||||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
import example
|
||||
|
||||
# PythonBinaryOp class is defined and derived from C++ class BinaryOp
|
||||
class PythonBinaryOp(example.BinaryOp):
|
||||
|
||||
# Define Python class 'constructor'
|
||||
def __init__(self):
|
||||
# Call C++ base class constructor
|
||||
example.BinaryOp.__init__(self)
|
||||
|
||||
# Override C++ method: virtual int handle(int a, int b) = 0;
|
||||
def handle(self, a, b):
|
||||
# Return the product
|
||||
return a * b
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
For this to work from Python, an instance of the <tt>PythonBinaryOp</tt> class is created
|
||||
and then passed to <tt>binary_op_wrapper</tt>. The net result is the <tt>binary_op</tt>
|
||||
function will in turn be called which will call <tt>handler_helper</tt> which will call
|
||||
the virtual <tt>handle</tt> method, that is, the Python method <tt>handle</tt> in the PythonBinaryOp class. The result will be the product of 10 and 20 and make its way back to Python and hence
|
||||
200 will be printed with the following code:
|
||||
</p>
|
||||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
handler = PythonBinaryOp()
|
||||
result = example.binary_op_wrapper(10, 20, handler)
|
||||
print result
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This has thus demonstrated a C/C++ function pointer calling back into a target language function.
|
||||
The code could be made a little more user friendly by using <tt>%rename</tt> to provide the
|
||||
original <tt>binary_op</tt> name from the target language instead of <tt>binary_op_wrapper</tt>.
|
||||
A C++ functor base class and Python functor class
|
||||
could also be used instead, but these are left as exercises for the reader.
|
||||
</p>
|
||||
|
||||
<H2><a name="SWIGPlus_nn42">6.30 Where to go for more information</a></H2>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@
|
|||
<li><a href="#Typemaps_nn35">"memberin" typemap</a>
|
||||
<li><a href="#Typemaps_nn36">"varin" typemap</a>
|
||||
<li><a href="#Typemaps_nn37">"varout" typemap</a>
|
||||
<li><a href="#throws_typemap">"throws" typemap</a>
|
||||
<li><a href="#Typemaps_throws_typemap">"throws" typemap</a>
|
||||
</ul>
|
||||
<li><a href="#Typemaps_nn39">Some typemap examples</a>
|
||||
<ul>
|
||||
|
|
@ -89,6 +89,9 @@
|
|||
<li><a href="#Typemaps_runtime_type_checker_usage">Usage</a>
|
||||
</ul>
|
||||
<li><a href="#Typemaps_overloading">Typemaps and overloading</a>
|
||||
<ul>
|
||||
<li><a href="#Typemaps_typecheck_pointer">SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap</a>
|
||||
</ul>
|
||||
<li><a href="#Typemaps_nn48">More about %apply and %clear</a>
|
||||
<li><a href="#Typemaps_nn47">Passing data between typemaps</a>
|
||||
<li><a href="#Typemaps_nn52">C++ "this" pointer</a>
|
||||
|
|
@ -2881,11 +2884,11 @@ The "varout" typemap is used to convert a C/C++ object to an object in the targe
|
|||
language when reading a C/C++ global variable. This is implementation specific.
|
||||
</p>
|
||||
|
||||
<H3><a name="throws_typemap">11.5.14 "throws" typemap</a></H3>
|
||||
<H3><a name="Typemaps_throws_typemap">11.5.14 "throws" typemap</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the <tt>%catches</tt> feature attached to the method.
|
||||
The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the <tt>%catches</tt> feature attached to the method (see <a href="SWIGPlus.html#SWIGPlus_catches">Exception handling with %catches</a>).
|
||||
It provides a default mechanism for handling C++ methods that have declared the exceptions they will throw.
|
||||
The purpose of this typemap is to convert a C++ exception into an error or exception in the target language.
|
||||
It is slightly different to the other typemaps as it is based around the exception type rather than the type of a parameter or variable.
|
||||
|
|
@ -2898,13 +2901,19 @@ For example:
|
|||
PyErr_SetString(PyExc_RuntimeError, $1);
|
||||
SWIG_fail;
|
||||
%}
|
||||
void bar() throw (const char *);
|
||||
|
||||
// Either an exception specification on the method
|
||||
void bar() throw (const char *);
|
||||
|
||||
// Or a %catches feature attached to the method
|
||||
%catches(const char *) bar();
|
||||
void bar();
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
As can be seen from the generated code below, SWIG generates an exception handler
|
||||
with the catch block comprising the "throws" typemap content.
|
||||
As can be seen from the resulting generated code below, SWIG generates an exception handler
|
||||
when wrapping the <tt>bar</tt> function with the catch block comprising the "throws" typemap content.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -2912,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;
|
||||
}
|
||||
|
|
@ -2922,8 +2930,8 @@ catch(char const *_e) {
|
|||
</div>
|
||||
|
||||
<p>
|
||||
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 <a href="Customization.html#Customization_exception">Exception handling with %exception</a> section.
|
||||
Note that if your methods do not have an exception specification but they do throw exceptions and you are not using <tt>%catches</tt>, SWIG cannot know how to deal with them.
|
||||
Please also see the <a href="Customization.html#Customization_exception">Exception handling with %exception</a> section for another way to handle exceptions.
|
||||
</p>
|
||||
|
||||
<H2><a name="Typemaps_nn39">11.6 Some typemap examples</a></H2>
|
||||
|
|
@ -4754,7 +4762,8 @@ then the type is given a precedence higher than any other known precedence level
|
|||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type checking rule - no precedence level in typecheck typemap for 'int').
|
||||
example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type
|
||||
checking rule - no precedence level in typecheck typemap for 'int').
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
|
@ -4779,10 +4788,112 @@ simply check the type of the first array element and use that to dispatch to the
|
|||
Subsequent "in" typemaps would then perform more extensive type-checking.
|
||||
</li>
|
||||
|
||||
<li>Make sure you read the section on overloading in the "<a href="SWIGPlus.html#SWIGPlus">SWIG and C++</a>" chapter.
|
||||
<li>Make sure you read the section on <a href="SWIGPlus.html#SWIGPlus_overloaded_methods">overloading</a> in the SWIG and C++ chapter.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<H3><a name="Typemaps_typecheck_pointer">11.13.1 SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
When it comes to overloading of a particular type passed by value, pointer or reference (const and non-const),
|
||||
a C++ compiler can disambiguate which overloaded function to call.
|
||||
However, SWIG effectively treats these as pointers in the target language and thus as equivalent types.
|
||||
For example, consider:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
class X { ... };
|
||||
void m(X const &c); // equivalent: void m(X *c);
|
||||
void m(X &r); // equivalent: void m(X *r);
|
||||
void m(X *p); // equivalent: void m(X *p);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
These cannot be disambiguated in the target languages and so SWIG will choose the first method and ignore the subsequent two methods.
|
||||
The scripting languages do this by using the overload dispatch mechanism described earlier and warnings indicate this:
|
||||
</p>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
example.i:6: Warning 509: Overloaded method m(X &) effectively ignored,
|
||||
example.i:5: Warning 509: as it is shadowed by m(X const &).
|
||||
example.i:7: Warning 509: Overloaded method m(X *) effectively ignored,
|
||||
example.i:5: Warning 509: as it is shadowed by m(X const &).
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The statically typed languages like Java and C# automatically ignore all but the first equivalent overloaded methods with warnings:
|
||||
</p>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
example.i:6: Warning 516: Overloaded method m(X &) ignored,
|
||||
example.i:5: Warning 516: using m(X const &) instead.
|
||||
example.i:7: Warning 516: Overloaded method m(X *) ignored,
|
||||
example.i:5: Warning 516: using m(X const &) instead.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
You can select the overloaded method you would like to wrap by ignoring the other two with <tt>%ignore</tt> or rename two of them with <tt>%rename</tt>
|
||||
and this will of course remove the warnings too.
|
||||
The problem of ambiguity is also discussed in the C++ chapter on <a href="SWIGPlus.html#SWIGPlus_overloaded_methods">overloading</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
So how does this work with respect to typemaps?
|
||||
The typemaps SWIG provides to handle overloading for these three methods are from the SWIGTYPE family.
|
||||
As discussed earlier, in <a href="Typemaps.html#Typemaps_nn19">Default typemap matching rules</a>,
|
||||
the <tt>SWIGTYPE &</tt> typemaps are used for references and <tt>SWIGTYPE *</tt> typemaps are used for pointers.
|
||||
SWIG uses the special <tt>SWIG_TYPECHECK_POINTER</tt> (0) precedence level to handle these types in the "typecheck" typemap:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE & "..."
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE * "..."
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
When the SWIGTYPE "typecheck" typemaps use the <tt>SWIG_TYPECHECK_POINTER</tt> precedence level,
|
||||
SWIG converts the type to a pointer equivalent type and then uses the equivalent type to detect if it can be disambiguated in an overloaded method in the target language.
|
||||
In our example above, the equivalent types for <tt>X const &</tt>, <tt>X &</tt> and <tt>X *</tt> are all <tt>X *</tt>.
|
||||
As they are the same, they cannot be disambiguated and so just the first overloaded method is chosen.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The automatic conversion to equivalent types and subsequent type comparison is triggered via the use of the special <tt>SWIG_TYPECHECK_POINTER</tt> precedence level
|
||||
and works for types passed by value, pointer and reference.
|
||||
Alas, there are more ways to overload a method that also need handling.
|
||||
C++ smart pointers are such a type which can be disambiguated by a C++ compiler but not automatically by SWIG.
|
||||
SWIG does not automatically know that a smart pointer has an equivalent type, but it can be told manually.
|
||||
Just specify the 'equivalent' attribute in the "typecheck" typemap with a pointer to the underlying type.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="X *") MySmartPtr<X> " ... "
|
||||
|
||||
void m(X &r); // equivalent: void m(X *r);
|
||||
void m(MySmartPtr<X> s); // equivalent: void m(X *s);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Now SWIG will detect the two types are equivalent and generate valid code by wrapping just the first overloaded method.
|
||||
You can of course choose which method to wrap by ignoring one of them with <tt>%ignore</tt>.
|
||||
Otherwise both can be wrapped by removing the overloading name ambiguity by renaming one of them with <tt>%rename</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The 'equivalent' attribute is used in the implementation for the <a href="Library.html#Library_std_shared_ptr">shared_ptr smart pointer</a> library.
|
||||
</p>
|
||||
|
||||
<H2><a name="Typemaps_nn48">11.14 More about %apply and %clear</a></H2>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -529,8 +529,11 @@ like this:
|
|||
SWIG_fail;
|
||||
}
|
||||
pystr = PyUnicode_AsUTF8String(pyobj);
|
||||
if (!pystr) {
|
||||
SWIG_fail;
|
||||
}
|
||||
str = strdup(PyBytes_AsString(pystr));
|
||||
Py_XDECREF(pystr);
|
||||
Py_DECREF(pystr);
|
||||
%#else
|
||||
if (!PyString_Check(pyobj)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expected a string");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue