explicitcall docs

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@9195 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2006-07-04 21:16:14 +00:00
commit 714971a14a
3 changed files with 158 additions and 14 deletions

View file

@ -3203,6 +3203,60 @@ directorDerived::upcall_method() invoked.
</pre>
</div>
<H3><a name="java_directors_explicitcall"></a>Director base method calls</H3>
<p>
There is a limitation with Java directors when calling a base class method from an overridden method.
A <tt>java.lang.StackOverflowError</tt> exception will be thrown as the code makes recursive calls from the C++ layer
to the Java layer and back again in the same method. The <a href="SWIGPlus.html#SWIGPlus_explicitcall">explicitcall feature flag</a>
is one way to work around this problem. Consider the following C++ code:
</p>
<div class="code">
<pre>
%feature("director");
%feature("explicitcall");
%include &lt;std_string.i&gt;
%inline %{
struct Thing {
virtual std::string getit() { return "Thing"; }
virtual ~Thing() {}
};
%}
</pre>
</div>
<p>
and the following Java class:
</p>
<div class="code">
<pre>
class JavaThing extends Thing {
public String getit() {
return "Java" + super.getit();
}
}
</pre>
</div>
<p>
The overridden <tt>JavaThing.getit()</tt> method will throw the <tt>java.lang.StackOverflowError</tt> exception when called.
Fixing this would impose a performance penalty on all director methods and would not be able to automatically deal with pure
virtual methods for which a method body is not always defined. Instead, users are advised to use the explicitcall
feature flag which generates an additional method <tt>getitThing()</tt>. The modified version will then avoid the recursive calls:
</p>
<div class="code">
<pre>
class JavaThing extends Thing {
public String getit() {
return "Java" + super.getitThing();
}
}
</pre>
</div>
<H2><a name="common_customization"></a>20.6 Common customization features</H2>

View file

@ -1666,6 +1666,84 @@ functions for virtual members that are already defined in a base
class.
</p>
<H3><a name="SWIGPlus_explicitcall"></a>Explicit base class method calls</H3>
<p>
SWIG uses standard C++ polymorphic behaviour to ensure the correct virtual method is called
when generating wrappers for virtual methods.
However, in C++ it is possible, albeit rare, to call a particular base class method in the inheritance
hierarchy. This C++ functionality is available to target languages with the
<tt>explicitcall</tt> <a href="Customization.html#Customization_feature_flags">feature flag</a> directive.
This feature only works on virtual methods and when it is specified it generates an
additional wrapper method. By default, the name of this method is the original method name mangled with
the name of the class as a suffix. However, the name of the method can be controlled by specifying a different
suffix in the <tt>suffix</tt>
<a href="Customization.html#Customization_feature_attributes">feature attribute</a>.
For example, consider the following code:
</p>
<div class="code">
<pre>
%explicitcall; // enable explicitcall feature for all virtual methods
%feature("explicitcall", suffix="Bambino") Child::describe;
struct Person {
Person() {}
virtual const char * describe() { return "Person"; }
virtual ~Person() {}
};
struct Child : Person {
virtual const char * describe() { return "Child"; }
};
</pre>
</div>
<p>
From Python, it is then possible to call explicit methods in the inheritance hierarchy.
Note the suffix names:
</p>
<div class="targetlang">
<pre>
$ python
&gt;&gt;&gt; from example import *
&gt;&gt;&gt; child = Child()
&gt;&gt;&gt; print child.describe() # normal polymorphic call
Child
&gt;&gt;&gt; print child.describePerson() # explicit Person::describe call
Person
&gt;&gt;&gt; print child.describeBambino() # explicit Child::describe call
Child
</div>
<p>
The pseudo C++ code generated for the <tt>Person::describe</tt> methods is as follows:
</p>
<div class="code">
<pre>
// Normal virtual method wrapper
const char * Person_talk(Person *obj) {
const char * ret = obj-&gt;describe();
return ret;
}
// Additional wrapper due to %explicitcall
const char * Person_talkPerson(Person *obj) {
const char * ret = obj-&gt;Person::describe();
return ret;
}
</pre>
</div>
<p>
Please note that if this feature is enabled globally, it will apply to all virtual methods.
This includes pure virtual methods which may or may not have a body defined.
If, as is often the case, your pure virtual methods do not have a body defined you might get unresolved linker errors on some platforms.
<tt>%noexplicitcall</tt> can then be used to turn this feature off for the problem methods.
</p>
<H2><a name="SWIGPlus_nn21"></a>6.13 A brief discussion of multiple inheritance, pointers, and type checking</H2>
@ -1777,20 +1855,27 @@ generated wrappers to correctly cast pointer values under inheritance
</p>
<p>
Some of the language modules are able to solve the problem by storing multiple instance of the pointer, for example, <tt>A *</tt>,
in the A proxy class and <tt>C *</tt> in the C proxy class. The correct cast can then be made:
Some of the language modules are able to solve the problem by storing multiple instances of the pointer, for example, <tt>A *</tt>,
in the A proxy class as well as <tt>C *</tt> in the C proxy class. The correct cast can then be made by choosing the correct <tt>void *</tt>
pointer to use and is guaranteed to work as the cast to a void pointer and back to the same type does not lose any type information:
</p>
<div class="code">
<pre>
C *c = new C();
void *p = (void *) c;
void *pA = (void *) c;
void *pB = (void *) c;
...
int x = A_function((C *) p);
int y = B_function((C *) p);
int x = A_function((A *) pA);
int y = B_function((B *) pB);
</pre>
</div>
<p>
In practice, the pointer is held as an integral number in the target language proxy class.
</p>
<H2><a name="SWIGPlus_overloaded_methods"></a>6.15 Wrapping Overloaded Functions and Methods</H2>
@ -3093,19 +3178,24 @@ you might consider writing a SWIG macro. For example:
<div class="code">
<pre>
%define TEMPLATE_WRAP(T,prefix)
%template(prefix ## Foo) Foo&lt;T&gt;;
%template(prefix ## Bar) Bar&lt;T&gt;;
%define TEMPLATE_WRAP(prefix, T...)
%template(prefix ## Foo) Foo&lt;T &gt;;
%template(prefix ## Bar) Bar&lt;T &gt;;
...
%enddef
TEMPLATE_WRAP(int, int)
TEMPLATE_WRAP(double, double)
TEMPLATE_WRAP(char *, String)
TEMPLATE_WRAP(String, char *)
TEMPLATE_WRAP(PairStringInt, std::pair&lt;string, int&gt;)
...
</pre>
</div>
<p>
Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in last example would not be possible.
</p>
<p>
The SWIG template mechanism <em>does</em> support specialization. For instance, if you define
a class like this,
@ -3547,7 +3637,7 @@ Similar changes apply to typemaps and other customization features.
<p>
Support for C++ namespaces is a relatively late addition to SWIG,
first appearing in SWIG-1.3.12. Before describing the implementation,
it is worth nothing that the semantics of C++ namespaces is extremely
it is worth noting that the semantics of C++ namespaces is extremely
non-trivial--especially with regard to the C++ type system and class
machinery. At a most basic level, namespaces are sometimes used to
encapsulate common functionality. For example:
@ -3659,7 +3749,7 @@ void evil(A::Foo *a, B::FooClass *b, B::C::Foo *c, BIGB::FooClass *d,
Given the possibility for such perversion, it's hard to imagine how
every C++ programmer might want such code wrapped into the target
language. Clearly this code defines three different classes. However, one
of those classes is accessible under at least six different class names!
of those classes is accessible under at least six different names!
</p>
<p>
@ -4005,7 +4095,7 @@ except Error,e:
</div>
<p>
Details of how to tailor code for handling the caught C++ exception and converts it into the target language's exception/error handling mechanism
Details of how to tailor code for handling the caught C++ exception and converting it into the target language's exception/error handling mechanism
is outlined in the <a href="Typemaps.html#throws_typemap">"throws" typemap</a> section.
</p>
@ -4522,7 +4612,7 @@ public:
<p>
The next workaround assumes you cannot modify the source code as was done above and it provides a solution for methods that use nested class types.
Imagine we are wrapping the <tt>Outer</tt> class with a nested class <tt>Inner</tt>:
Imagine we are wrapping the <tt>Outer</tt> class which contains a nested class <tt>Inner</tt>:
</p>
<div class="code">

View file

@ -11,7 +11,7 @@
<div class="sectiontoc">
<ul>
<li><a href="#Warnings_nn2">Introduction</a>
<li><a href="#Warnings_nn3">Warning message suppression</a>
<li><a href="#Warnings_suppression">Warning message suppression</a>
<li><a href="#Warnings_nn4">Enabling additional warnings</a>
<li><a href="#Warnings_nn5">Issuing a warning message</a>
<li><a href="#Warnings_nn6">Commentary</a>
@ -54,7 +54,7 @@ where the generated wrapper code will probably compile, but it may not
work like you expect.
</p>
<H2><a name="Warnings_nn3"></a>14.2 Warning message suppression</H2>
<H2><a name="Warnings_suppression"></a>14.2 Warning message suppression</H2>
<p>