aboutsummaryrefslogtreecommitdiff
path: root/Doc/Manual
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/Manual')
-rw-r--r--Doc/Manual/Perl5.html366
1 files changed, 366 insertions, 0 deletions
diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html
index 49e8965fa..db8c0e602 100644
--- a/Doc/Manual/Perl5.html
+++ b/Doc/Manual/Perl5.html
@@ -68,6 +68,15 @@
<li><a href="#Perl5_nn46">Modifying the proxy methods</a>
</ul>
<li><a href="#Perl5_nn47">Adding additional Perl code</a>
+<li><a href="#Perl5_directors">Cross language polymorphism</a>
+<ul>
+<li><a href="#Perl5_nn48">Enabling directors</a>
+<li><a href="#Perl5_nn49">Director classes</a>
+<li><a href="#Perl5_nn50">Ownership and object destruction</a>
+<li><a href="#Perl5_nn51">Exception unrolling</a>
+<li><a href="#Perl5_nn52">Overhead and code bloat</a>
+<li><a href="#Perl5_nn53">Typemaps</a>
+</ul>
</ul>
</div>
<!-- INDEX -->
@@ -2993,6 +3002,363 @@ set_transform($im, $a);
</pre>
</div>
+<H2><a name="Perl5_directors"></a>31.11 Cross language polymorphism</H2>
+
+
+<p>
+Proxy classes provide a more natural, object-oriented way to access
+extension classes. As described above, each proxy instance has an
+associated C++ instance, and method calls to the proxy are passed to the
+C++ instance transparently via C wrapper functions.
+</p>
+
+<p>
+This arrangement is asymmetric in the sense that no corresponding
+mechanism exists to pass method calls down the inheritance chain from
+C++ to Perl. In particular, if a C++ class has been extended in Perl
+(by extending the proxy class), these extensions will not be visible
+from C++ code. Virtual method calls from C++ are thus not able access
+the lowest implementation in the inheritance chain.
+</p>
+
+<p>
+Changes have been made to SWIG to address this problem and
+make the relationship between C++ classes and proxy classes more
+symmetric. To achieve this goal, new classes called directors are
+introduced at the bottom of the C++ inheritance chain. The job of the
+directors is to route method calls correctly, either to C++
+implementations higher in the inheritance chain or to Perl
+implementations lower in the inheritance chain. The upshot is that C++
+classes can be extended in Perl and from C++ these extensions look
+exactly like native C++ classes. Neither C++ code nor Perl code needs
+to know where a particular method is implemented: the combination of
+proxy classes, director classes, and C wrapper functions takes care of
+all the cross-language method routing transparently.
+</p>
+
+<H3><a name="Perl5_nn48"></a>31.11.1 Enabling directors</H3>
+
+
+<p>
+The director feature is disabled by default. To use directors you
+must make two changes to the interface file. First, add the "directors"
+option to the %module directive, like this:
+</p>
+
+<div class="code">
+<pre>
+%module(directors="1") modulename
+</pre>
+</div>
+
+<p>
+Without this option no director code will be generated. Second, you
+must use the %feature("director") directive to tell SWIG which classes
+and methods should get directors. The %feature directive can be applied
+globally, to specific classes, and to specific methods, like this:
+</p>
+
+<div class="code">
+<pre>
+// generate directors for all classes that have virtual methods
+%feature("director");
+
+// generate directors for all virtual methods in class Foo
+%feature("director") Foo;
+</pre>
+</div>
+
+<p>
+You can use the %feature("nodirector") directive to turn off
+directors for specific classes or methods. So for example,
+</p>
+
+<div class="code">
+<pre>
+%feature("director") Foo;
+%feature("nodirector") Foo::bar;
+</pre>
+</div>
+
+<p>
+will generate directors for all virtual methods of class Foo except
+bar().
+</p>
+
+<p>
+Directors can also be generated implicitly through inheritance.
+In the following, class Bar will get a director class that handles
+the methods one() and two() (but not three()):
+</p>
+
+<div class="code">
+<pre>
+%feature("director") Foo;
+class Foo {
+public:
+ Foo(int foo);
+ virtual void one();
+ virtual void two();
+};
+
+class Bar: public Foo {
+public:
+ virtual void three();
+};
+</pre>
+</div>
+
+<p>
+then at the Perl side you can define
+</p>
+
+<div class="targetlang">
+<pre>
+use mymodule;
+
+package MyFoo;
+use base 'mymodule::Foo';
+
+sub one {
+ print "one from Perl\n";
+}
+</pre>
+</div>
+
+
+<H3><a name="Perl5_nn49"></a>31.11.2 Director classes</H3>
+
+
+
+
+
+<p>
+For each class that has directors enabled, SWIG generates a new class
+that derives from both the class in question and a special
+<tt>Swig::Director</tt> class. These new classes, referred to as director
+classes, can be loosely thought of as the C++ equivalent of the Perl
+proxy classes. The director classes store a pointer to their underlying
+Perl object and handle various issues related to object ownership.
+</p>
+
+<p>
+For simplicity let's ignore the <tt>Swig::Director</tt> class and refer to the
+original C++ class as the director's base class. By default, a director
+class extends all virtual methods in the inheritance chain of its base
+class (see the preceding section for how to modify this behavior).
+Thus all virtual method calls, whether they originate in C++ or in
+Perl via proxy classes, eventually end up in at the implementation in
+the director class. The job of the director methods is to route these
+method calls to the appropriate place in the inheritance chain. By
+"appropriate place" we mean the method that would have been called if
+the C++ base class and its extensions in Perl were seamlessly
+integrated. That seamless integration is exactly what the director
+classes provide, transparently skipping over all the messy extension API
+glue that binds the two languages together.
+</p>
+
+<p>
+In reality, the "appropriate place" is one of only two possibilities:
+C++ or Perl. Once this decision is made, the rest is fairly easy. If
+the correct implementation is in C++, then the lowest implementation of
+the method in the C++ inheritance chain is called explicitly. If the
+correct implementation is in Perl, the Perl API is used to call the
+method of the underlying Perl object (after which the usual virtual
+method resolution in Perl automatically finds the right
+implementation).
+</p>
+
+<p>
+Now how does the director decide which language should handle the method call?
+The basic rule is to handle the method in Perl, unless there's a good
+reason not to. The reason for this is simple: Perl has the most
+"extended" implementation of the method. This assertion is guaranteed,
+since at a minimum the Perl proxy class implements the method. If the
+method in question has been extended by a class derived from the proxy
+class, that extended implementation will execute exactly as it should.
+If not, the proxy class will route the method call into a C wrapper
+function, expecting that the method will be resolved in C++. The wrapper
+will call the virtual method of the C++ instance, and since the director
+extends this the call will end up right back in the director method. Now
+comes the "good reason not to" part. If the director method were to blindly
+call the Perl method again, it would get stuck in an infinite loop. We avoid this
+situation by adding special code to the C wrapper function that tells
+the director method to not do this. The C wrapper function compares the
+pointer to the Perl object that called the wrapper function to the
+pointer stored by the director. If these are the same, then the C
+wrapper function tells the director to resolve the method by calling up
+the C++ inheritance chain, preventing an infinite loop.
+</p>
+
+<p>
+One more point needs to be made about the relationship between director
+classes and proxy classes. When a proxy class instance is created in
+Perl, SWIG creates an instance of the original C++ class.
+This is exactly what happens without directors and
+is true even if directors are enabled for the particular class in
+question. When a class <i>derived</i> from a proxy class is created,
+however, SWIG then creates an instance of the corresponding C++ director
+class. The reason for this difference is that user-defined subclasses
+may override or extend methods of the original class, so the director
+class is needed to route calls to these methods correctly. For
+unmodified proxy classes, all methods are ultimately implemented in C++
+so there is no need for the extra overhead involved with routing the
+calls through Perl.
+</p>
+
+<H3><a name="Perl5_nn50"></a>31.11.3 Ownership and object destruction</H3>
+
+
+<p>
+Memory management issues are slightly more complicated with directors
+than for proxy classes alone. Perl instances hold a pointer to the
+associated C++ director object, and the director in turn holds a pointer
+back to a Perl object. By default, proxy classes own their C++
+director object and take care of deleting it when they are garbage
+collected.
+</p>
+
+<p>
+This relationship can be reversed by calling the special
+<tt>DISOWN()</tt> method of the proxy class. After calling this
+method the director
+class increments the reference count of the Perl object. When the
+director class is deleted it decrements the reference count. Assuming no
+outstanding references to the Perl object remain, the Perl object
+will be destroyed at the same time. This is a good thing, since
+directors and proxies refer to each other and so must be created and
+destroyed together. Destroying one without destroying the other will
+likely cause your program to segfault.
+</p>
+
+<p>
+Also note that due to the proxy implementation, the <tt>DESTROY()</tt>
+method on directors can be called for several reasons, many of which
+have little to do with the teardown of an object instance. To help
+disambiguate this, a second argument is added to the <tt>DESTROY()</tt>
+call when a C++ director object is being released. So, to avoid running
+your clean-up code when an object is not really going away, or after it
+has already been reclaimed, it is suggested that custom destructors in
+Perl subclasses looks something like:
+</p>
+
+<div class="targetlang">
+<pre>
+sub DESTROY {
+ my($self, $final) = @_;
+ if($final) {
+ # real teardown code
+ }
+ shift-&gt;SUPER::DESTROY(@_);
+}
+</pre>
+</div>
+
+
+<H3><a name="Perl5_nn51"></a>31.11.4 Exception unrolling</H3>
+
+
+<p>
+With directors routing method calls to Perl, and proxies routing them
+to C++, the handling of exceptions is an important concern. By default, the
+directors ignore exceptions that occur during method calls that are
+resolved in Perl. To handle such exceptions correctly, it is necessary
+to temporarily translate them into C++ exceptions. This can be done with
+the %feature("director:except") directive. The following code should
+suffice in most cases:
+</p>
+
+<div class="code">
+<pre>
+%feature("director:except") {
+ if ($error != NULL) {
+ throw Swig::DirectorMethodException();
+ }
+}
+</pre>
+</div>
+
+<p>
+This code will check the Perl error state after each method call from
+a director into Perl, and throw a C++ exception if an error occurred.
+This exception can be caught in C++ to implement an error handler.
+</p>
+
+<p>
+It may be the case that a method call originates in Perl, travels up
+to C++ through a proxy class, and then back into Perl via a director
+method. If an exception occurs in Perl at this point, it would be nice
+for that exception to find its way back to the original caller. This can
+be done by combining a normal %exception directive with the
+<tt>director:except</tt> handler shown above. Here is an example of a
+suitable exception handler:
+</p>
+
+<div class="code">
+<pre>
+%exception {
+ try { $action }
+ catch (Swig::DirectorException &amp;e) { SWIG_fail; }
+}
+</pre>
+</div>
+
+<p>
+The class Swig::DirectorException used in this example is actually a
+base class of Swig::DirectorMethodException, so it will trap this
+exception. Because the Perl error state is still set when
+Swig::DirectorMethodException is thrown, Perl will register the
+exception as soon as the C wrapper function returns.
+</p>
+
+<H3><a name="Perl5_nn52"></a>31.11.5 Overhead and code bloat</H3>
+
+
+<p>
+Enabling directors for a class will generate a new director method for
+every virtual method in the class' inheritance chain. This alone can
+generate a lot of code bloat for large hierarchies. Method arguments
+that require complex conversions to and from target language types can
+result in large director methods. For this reason it is recommended that
+you selectively enable directors only for specific classes that are
+likely to be extended in Perl and used in C++.
+</p>
+
+<p>
+Compared to classes that do not use directors, the call routing in the
+director methods does add some overhead. In particular, at least one
+dynamic cast and one extra function call occurs per method call from
+Perl. Relative to the speed of Perl execution this is probably
+completely negligible. For worst case routing, a method call that
+ultimately resolves in C++ may take one extra detour through Perl in
+order to ensure that the method does not have an extended Perl
+implementation. This could result in a noticeable overhead in some cases.
+</p>
+
+<p>
+Although directors make it natural to mix native C++ objects with Perl
+objects (as director objects) via a common base class pointer, one
+should be aware of the obvious fact that method calls to Perl objects
+will be much slower than calls to C++ objects. This situation can be
+optimized by selectively enabling director methods (using the %feature
+directive) for only those methods that are likely to be extended in
+Perl.
+</p>
+
+<H3><a name="Perl5_nn53"></a>31.11.6 Typemaps</H3>
+
+
+<p>
+Typemaps for input and output of most of the basic types from director
+classes have been written. These are roughly the reverse of the usual
+input and output typemaps used by the wrapper code. The typemap
+operation names are 'directorin', 'directorout', and 'directorargout'.
+The director code does not currently use any of the other kinds of typemaps.
+It is not clear at this point which kinds are appropriate and
+need to be supported.
+</p>
+
+
</body>