diff options
Diffstat (limited to 'Doc/Manual/Perl5.html')
| -rw-r--r-- | Doc/Manual/Perl5.html | 3001 |
1 files changed, 3001 insertions, 0 deletions
diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html new file mode 100644 index 0000000..8f74bd1 --- /dev/null +++ b/Doc/Manual/Perl5.html @@ -0,0 +1,3001 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>SWIG and Perl5</title> +<link rel="stylesheet" type="text/css" href="style.css"> +</head> + +<body bgcolor="#ffffff"> +<H1><a name="Perl5"></a>28 SWIG and Perl5</H1> +<!-- INDEX --> +<div class="sectiontoc"> +<ul> +<li><a href="#Perl5_nn2">Overview</a> +<li><a href="#Perl5_nn3">Preliminaries</a> +<ul> +<li><a href="#Perl5_nn4">Getting the right header files</a> +<li><a href="#Perl5_nn5">Compiling a dynamic module</a> +<li><a href="#Perl5_nn6">Building a dynamic module with MakeMaker</a> +<li><a href="#Perl5_nn7">Building a static version of Perl</a> +<li><a href="#Perl5_nn8">Using the module</a> +<li><a href="#Perl5_nn9">Compilation problems and compiling with C++</a> +<li><a href="#Perl5_nn10">Compiling for 64-bit platforms</a> +</ul> +<li><a href="#Perl5_nn11">Building Perl Extensions under Windows</a> +<ul> +<li><a href="#Perl5_nn12">Running SWIG from Developer Studio</a> +<li><a href="#Perl5_nn13">Using other compilers</a> +</ul> +<li><a href="#Perl5_nn14">The low-level interface</a> +<ul> +<li><a href="#Perl5_nn15">Functions</a> +<li><a href="#Perl5_nn16">Global variables</a> +<li><a href="#Perl5_nn17">Constants</a> +<li><a href="#Perl5_nn18">Pointers</a> +<li><a href="#Perl5_nn19">Structures</a> +<li><a href="#Perl5_nn20">C++ classes</a> +<li><a href="#Perl5_nn21">C++ classes and type-checking</a> +<li><a href="#Perl5_nn22">C++ overloaded functions</a> +<li><a href="#Perl5_nn23">Operators</a> +<li><a href="#Perl5_nn24">Modules and packages</a> +</ul> +<li><a href="#Perl5_nn25">Input and output parameters</a> +<li><a href="#Perl5_nn26">Exception handling</a> +<li><a href="#Perl5_nn27">Remapping datatypes with typemaps</a> +<ul> +<li><a href="#Perl5_nn28">A simple typemap example</a> +<li><a href="#Perl5_nn29">Perl5 typemaps</a> +<li><a href="#Perl5_nn30">Typemap variables</a> +<li><a href="#Perl5_nn31">Useful functions</a> +</ul> +<li><a href="#Perl5_nn32">Typemap Examples</a> +<ul> +<li><a href="#Perl5_nn33">Converting a Perl5 array to a char **</a> +<li><a href="#Perl5_nn34">Return values</a> +<li><a href="#Perl5_nn35">Returning values from arguments</a> +<li><a href="#Perl5_nn36">Accessing array structure members</a> +<li><a href="#Perl5_nn37">Turning Perl references into C pointers</a> +<li><a href="#Perl5_nn38">Pointer handling</a> +</ul> +<li><a href="#Perl5_nn39">Proxy classes</a> +<ul> +<li><a href="#Perl5_nn40">Preliminaries</a> +<li><a href="#Perl5_nn41">Structure and class wrappers</a> +<li><a href="#Perl5_nn42">Object Ownership</a> +<li><a href="#Perl5_nn43">Nested Objects</a> +<li><a href="#Perl5_nn44">Proxy Functions</a> +<li><a href="#Perl5_nn45">Inheritance</a> +<li><a href="#Perl5_nn46">Modifying the proxy methods</a> +</ul> +<li><a href="#Perl5_nn47">Adding additional Perl code</a> +</ul> +</div> +<!-- INDEX --> + + + +<p> +<b>Caution: This chapter is under repair!</b> +</p> + +<p> +This chapter describes SWIG's support of Perl5. Although the Perl5 +module is one of the earliest SWIG modules, it has continued to evolve +and has been improved greatly with the help of SWIG users. For the +best results, it is recommended that SWIG be used with Perl5.003 or +later. Earlier versions are problematic and SWIG generated extensions +may not compile or run correctly. +</p> + +<H2><a name="Perl5_nn2"></a>28.1 Overview</H2> + + +<p> +To build Perl extension modules, SWIG uses a layered approach. At +the lowest level, simple procedural wrappers are generated for +functions, classes, methods, and other declarations in the input file. +Then, for structures and classes, an optional collection of Perl +proxy classes can be generated in order to provide a more natural object oriented Perl +interface. These proxy classes simply build upon the low-level interface. +</p> + +<p> +In describing the Perl interface, this chapter begins by covering the +essentials. First, the problem of configuration, compiling, +and installing Perl modules is discussed. Next, the low-level +procedural interface is presented. Finally, proxy classes are +described. Advanced customization features, typemaps, and other +options are found near the end of the chapter. +</p> + +<H2><a name="Perl5_nn3"></a>28.2 Preliminaries</H2> + + +<p> +To build a Perl5 module, run Swig using the <tt>-perl</tt> option as +follows : +</p> + +<div class="code"><pre> +swig -perl example.i + +</pre></div> + +<p> +This produces two files. The first file, <tt>example_wrap.c</tt> +contains all of the C code needed to build a Perl5 module. The second +file, <tt>example.pm</tt> contains supporting Perl code needed to +properly load the module. +</p> + +<p> +To build the module, you will need to compile the file +<tt>example_wrap.c</tt> and link it with the rest of your program. +</p> + +<H3><a name="Perl5_nn4"></a>28.2.1 Getting the right header files</H3> + + +<p> +In order to compile, SWIG extensions need the following Perl5 header files :</p> + +<div class="code"><pre> +#include "Extern.h" +#include "perl.h" +#include "XSUB.h" +</pre></div> + +<p> +These are typically located in a directory like this</p> + +<div class="code"><pre> +/usr/lib/perl5/5.00503/i386-linux/CORE +</pre></div> + +<p> +The SWIG configuration script automatically tries to locate this directory so +that it can compile examples. However, if you need to find out where the directory is +loaded, an easy way to find out is to run Perl itself. +</p> + +<div class="code"> +<pre> +% perl -e 'use Config; print $Config{archlib};' +/usr/lib/perl5/5.00503/i386-linux +</pre> +</div> + +<H3><a name="Perl5_nn5"></a>28.2.2 Compiling a dynamic module</H3> + + +<p> +The preferred approach to building an extension module is to compile it into +a shared object file or DLL. To do this, you will need to compile your program +using commands like this (shown for Linux): +</p> + +<div class="code"><pre> +$ swig -perl example.i +% gcc example.c +% gcc -c example_wrap.c -I/usr/lib/perl5/5.00503/i386-linux/CORE -Dbool=char +% gcc -shared example.o example_wrap.o -o example.so +</pre></div> + +<p> +The exact compiler options vary from platform to platform. +SWIG tries to guess the right options when it is installed. Therefore, +you may want to start with one of the examples in the <tt>SWIG/Examples/perl5</tt> +directory. If that doesn't work, you will need to read the man-pages for +your compiler and linker to get the right set of options. You might also +check the <a href="http://www.dabeaz.com/cgi-bin/wiki.pl">SWIG Wiki</a> for +additional information. +</p> + +<p> +When linking the module, the name of the shared object file must match the module name used in +the SWIG interface file. If you used `<tt>%module example</tt>', then +the target should be named `<tt>example.so</tt>', +`<tt>example.sl</tt>', or the appropriate dynamic module name on your system. +</p> + +<H3><a name="Perl5_nn6"></a>28.2.3 Building a dynamic module with MakeMaker</H3> + + +<p> +It is also possible to use Perl to build dynamically loadable modules +for you using the MakeMaker utility. To do this, write a Perl +script such as the following :</p> + +<div class="targetlang"><pre> +# File : Makefile.PL +use ExtUtils::MakeMaker; +WriteMakefile( + `NAME' => `example', # Name of package + `LIBS' => [`-lm'], # Name of custom libraries + `OBJECT' => `example.o example_wrap.o' # Object files +); + +</pre></div> + +<p> +Now, to build a module, simply follow these steps :</p> + +<div class="code"><pre> +% perl Makefile.PL +% make +% make install +</pre></div> + +<p> +If you are planning to distribute a SWIG-generated module, this is +the preferred approach to compilation. More information about MakeMaker can be +found in "Programming Perl, 2nd ed." by Larry Wall, Tom Christiansen, +and Randal Schwartz.</p> + +<H3><a name="Perl5_nn7"></a>28.2.4 Building a static version of Perl</H3> + + +<p> +If you machine does not support dynamic loading or if you've tried to +use it without success, you can build a new version of the Perl +interpreter with your SWIG extensions added to it. To build a static +extension, you first need to invoke SWIG as follows :</p> + +<div class="code"><pre> +% swig -perl -static example.i +</pre></div> + +<p> +By default SWIG includes code for dynamic loading, but the +<tt>-static</tt> option takes it out.</p> + +<p> +Next, you will need to supply a <tt>main()</tt> function that +initializes your extension and starts the Perl interpreter. While, +this may sound daunting, SWIG can do this for you automatically as +follows :</p> + +<div class="targetlang"><pre> +%module example + +%inline %{ +extern double My_variable; +extern int fact(int); +%} + +// Include code for rebuilding Perl +%include <perlmain.i> +</pre></div> + +<p> +The same thing can be accomplished by running SWIG as follows :</p> + +<div class="code"><pre> +% swig -perl -static -lperlmain.i example.i +</pre></div> + +<p> +The <tt>perlmain.i</tt> file inserts Perl's <tt>main()</tt> function +into the wrapper code and automatically initializes the SWIG generated +module. If you just want to make a quick a dirty module, this may be +the easiest way. By default, the <tt>perlmain.i</tt> code does not +initialize any other Perl extensions. If you need to use other +packages, you will need to modify it appropriately. You can do this by +just copying <tt>perlmain.i</tt> out of the SWIG library, placing it +in your own directory, and modifying it to suit your purposes.</p> + +<p> +To build your new Perl executable, follow the exact same procedure as +for a dynamic module, but change the link line to something like this: +</p> + +<div class="code"><pre> +% gcc example.o example_wrap.o -L/usr/lib/perl5/5.00503/i386-linux/CORE \ + -lperl -lsocket -lnsl -lm -o myperl +</pre></div> + +<p> +This will produce a new version of Perl called <tt>myperl</tt>. It +should be functionality identical to Perl with your C/C++ extension +added to it. Depending on your machine, you may need to link with +additional libraries such as <tt>-lsocket, -lnsl, -ldl</tt>, etc. +</p> + +<H3><a name="Perl5_nn8"></a>28.2.5 Using the module</H3> + + +<p> +To use the module, simply use the Perl <tt>use</tt> statement. If +all goes well, you will be able to do this: +</p> + +<div class="targetlang"><pre> +$ perl +use example; +print example::fact(4),"\n"; +24 +</pre></div> + +<p> +A common error received by first-time users is the following: +</p> + +<div class="targetlang"> +<pre> +use example; +Can't locate example.pm in @INC (@INC contains: /usr/lib/perl5/5.00503/i386-lin +ux /usr/lib/perl5/5.00503 /usr/lib/perl5/site_perl/5.005/i386-linux /usr/lib/pe +rl5/site_perl/5.005 .) at - line 1. +BEGIN failed--compilation aborted at - line 1. +</pre> +</div> + +<p> +This error is almost caused when the name of the shared object file you created doesn't match the module name +you specified with the <tt>%module</tt> directive. +</p> + +<p> +A somewhat related, but slightly different error is this: +</p> + +<div class="targetlang"> +<pre> +use example; +Can't find 'boot_example' symbol in ./example.so + at - line 1 +BEGIN failed--compilation aborted at - line 1. +</pre> +</div> + +<p> +This error is generated because Perl can't locate the module bootstrap function in the +SWIG extension module. This could be caused by a mismatch between the module name and the shared library name. +However, another possible cause is forgetting to link the SWIG-generated wrapper code with the rest +of your application when you linked the extension module. +</p> + +<p> +Another common error is the following: +</p> + +<div class="targetlang"> +<pre> +use example; +Can't load './example.so' for module example: ./example.so: +undefined symbol: Foo at /usr/lib/perl5/5.00503/i386-linux/DynaLoader.pm line 169. + + at - line 1 +BEGIN failed--compilation aborted at - line 1. +</pre> +</div> + +<p> +This error usually indicates that you forgot to include some object +files or libraries in the linking of the shared library file. Make +sure you compile both the SWIG wrapper file and your original program +into a shared library file. Make sure you pass all of the required libraries +to the linker. +</p> + +<p> +Sometimes unresolved symbols occur because a wrapper has been created +for a function that doesn't actually exist in a library. This usually +occurs when a header file includes a declaration for a function that +was never actually implemented or it was removed from a library +without updating the header file. To fix this, you can either edit +the SWIG input file to remove the offending declaration or you can use +the <tt>%ignore</tt> directive to ignore the declaration. Better yet, +update the header file so that it doesn't have an undefined declaration. +</p> + +<p> +Finally, suppose that your extension module is linked with another library like this: +</p> + +<div class="code"> +<pre> +$ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \ + -o example.so +</pre> +</div> + +<p> +If the <tt>foo</tt> library is compiled as a shared library, you might get the following +error when you try to use your module: +</p> + +<div class="targetlang"> +<pre> +use example; +Can't load './example.so' for module example: libfoo.so: cannot open shared object file: +No such file or directory at /usr/lib/perl5/5.00503/i386-linux/DynaLoader.pm line 169. + + at - line 1 +BEGIN failed--compilation aborted at - line 1. +>>> +</pre> +</div> + +<p> +This error is generated because the dynamic linker can't locate the +<tt>libfoo.so</tt> library. When shared libraries are loaded, the +system normally only checks a few standard locations such as +<tt>/usr/lib</tt> and <tt>/usr/local/lib</tt>. To get the loader to look in other +locations, there are several things you can do. First, you can recompile your extension +module with extra path information. For example, on Linux you can do this: +</p> + +<div class="code"> +<pre> +$ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \ + <b>-Xlinker -rpath /home/beazley/projects/lib \</b> + -o example.so +</pre> +</div> + +<p> +Alternatively, you can set the <tt>LD_LIBRARY_PATH</tt> environment +variable to include the directory with your shared libraries. If +setting <tt>LD_LIBRARY_PATH</tt>, be aware that setting this variable +can introduce a noticeable performance impact on all other +applications that you run. To set it only for Perl, you might want +to do this instead: +</p> + +<div class="code"> +<pre> +$ env LD_LIBRARY_PATH=/home/beazley/projects/lib perl +</pre> +</div> + +<p> +Finally, you can use a command such as <tt>ldconfig</tt> (Linux) or +<tt>crle</tt> (Solaris) to add additional search paths to the default +system configuration (this requires root access and you will need to +read the man pages). +</p> + +<H3><a name="Perl5_nn9"></a>28.2.6 Compilation problems and compiling with C++</H3> + + +<p> +Compilation of C++ extensions has traditionally been a tricky problem. +Since the Perl interpreter is written in C, you need to take steps to +make sure C++ is properly initialized and that modules are compiled +correctly. +</p> + +<p> +On most machines, C++ extension modules should be linked using the C++ +compiler. For example: +</p> + +<div class="code"><pre> +% swig -c++ -perl example.i +% g++ -c example.cxx +% g++ -c example_wrap.cxx -I/usr/lib/perl5/5.00503/i386-linux/CORE +% <b>g++ -shared example.o example_wrap.o -o example.so</b> +</pre></div> + +<p> +In addition to this, you may need to include additional library +files to make it work. For example, if you are using the Sun C++ compiler on +Solaris, you often need to add an extra library <tt>-lCrun</tt> like this: +</p> + +<div class="code"><pre> +% swig -c++ -perl example.i +% g++ -c example.cxx +% g++ -c example_wrap.cxx -I/usr/lib/perl5/5.00503/i386-linux/CORE +% g++ -shared example.o example_wrap.o -o example.so <b>-lCrun</b> +</pre></div> + +<p> +Of course, the names of the extra libraries are completely non-portable---you will +probably need to do some experimentation. +</p> + +<p> +Another possible compile problem comes from recent versions of Perl (5.8.0) and the GNU tools. +If you see errors having to do with _crypt_struct, that means _GNU_SOURCE is not defined and +it needs to be. So you should compile the wrapper like: +</p> + +<div class="code"><pre> +% g++ -c example_wrap.cxx -I/usr/lib/perl/5.8.0/CORE -D_GNU_SOURCE +</pre></div> + +<p> +-D_GNU_SOURCE is also included in the Perl ccflags, which can be found by running +</p> + +<div class="code"><pre> +% perl -e 'use Config; print $Config{ccflags};' +</pre></div> + +<p> +So you could also compile the wrapper like +</p> + +<div class="code"><pre> +% g++ -c example_wrap.cxx -I/usr/lib/perl/5.8.0/CORE \ +`perl -e 'use Config; print $Config{ccflags}'` +</pre></div> + +<p> +Sometimes people have suggested that it is necessary to relink the +Perl interpreter using the C++ compiler to make C++ extension modules work. +In the experience of this author, this has never actually appeared to be +necessary on most platforms. Relinking the interpreter with C++ really only includes the +special run-time libraries described above---as long as you link your extension +modules with these libraries, it should not be necessary to rebuild Perl. +</p> + +<p> +If you aren't entirely sure about the linking of a C++ extension, you +might look at an existing C++ program. On many Unix machines, the +<tt>ldd</tt> command will list library dependencies. This should give +you some clues about what you might have to include when you link your +extension module. For example, notice the first line of output here: +</p> + +<div class="code"> +<pre> +$ ldd swig + <b>libstdc++-libc6.1-1.so.2 => /usr/lib/libstdc++-libc6.1-1.so.2 (0x40019000)</b> + libm.so.6 => /lib/libm.so.6 (0x4005b000) + libc.so.6 => /lib/libc.so.6 (0x40077000) + /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) +$ +</pre> +</div> + +<p> +If linking wasn't enough of a problem, another major complication of C++ is that it does not +define any sort of standard for binary linking of libraries. This +means that C++ code compiled by different compilers will not link +together properly as libraries nor is the memory layout of classes and +data structures implemented in any kind of portable manner. In a +monolithic C++ program, this problem may be unnoticed. However, in Perl, it +is possible for different extension modules to be compiled with +different C++ compilers. As long as these modules are self-contained, +this probably won't matter. However, if these modules start sharing data, +you will need to take steps to avoid segmentation faults and other +erratic program behavior. Also, be aware that certain C++ features, especially RTTI, +can behave strangely when working with multiple modules. +</p> + +<p> +It should be noted that you may get a lot of error messages +about the `<tt>bool</tt>' datatype when compiling a C++ Perl module. If +you experience this problem, you can try the following :</p> + +<ul> +<li>Use <tt>-DHAS_BOOL</tt> when compiling the SWIG wrapper code +<li>Or use <tt>-Dbool=char</tt> when compiling. +</ul> + +<p> +Finally, recent versions of Perl (5.8.0) have namespace conflict problems. Perl defines a bunch +of short macros to make the Perl API function names shorter. For example, in +/usr/lib/perl/5.8.0/CORE/embed.h there is a line: +</p> + +<div class="code"><pre> +#define do_open Perl_do_open +</pre></div> + +<p> +The problem is, in the <iostream> header from GNU libstdc++v3 there is a private +function named do_open. If <iostream> is included after the perl headers, then +the Perl macro causes the iostream do_open to be renamed, which causes compile errors. +Hopefully in the future Perl will support a PERL_NO_SHORT_NAMES flag, but for now the +only solution is to undef the macros that conflict. Lib/perl5/noembed.h in the SWIG +source has a list of macros that are known to conflict with either standard headers or +other headers. But if you get macro type conflicts from other macros not included +in Lib/perl5/noembed.h while compiling the wrapper, you will +have to find the macro that conflicts and add an #undef into the .i file. Please report +any conflicting macros you find to <a href="http://www.swig.org/mail.html">swig-user mailing list</a>. +</p> + +<H3><a name="Perl5_nn10"></a>28.2.7 Compiling for 64-bit platforms</H3> + + +<p> +On platforms that support 64-bit applications (Solaris, Irix, etc.), +special care is required when building extension modules. On these +machines, 64-bit applications are compiled and linked using a different +set of compiler/linker options. In addition, it is not generally possible to mix +32-bit and 64-bit code together in the same application. +</p> + +<p> +To utilize 64-bits, the Perl executable will need to be recompiled +as a 64-bit application. In addition, all libraries, wrapper code, +and every other part of your application will need to be compiled for +64-bits. If you plan to use other third-party extension modules, they +will also have to be recompiled as 64-bit extensions. +</p> + +<p> +If you are wrapping commercial software for which you have no source +code, you will be forced to use the same linking standard as used by +that software. This may prevent the use of 64-bit extensions. It may +also introduce problems on platforms that support more than one +linking standard (e.g., -o32 and -n32 on Irix). +</p> + +<H2><a name="Perl5_nn11"></a>28.3 Building Perl Extensions under Windows</H2> + + +<p> +Building a SWIG extension to Perl under Windows is roughly +similar to the process used with Unix. Normally, you will want to +produce a DLL that can be loaded into the Perl interpreter. This +section assumes you are using SWIG with Microsoft Visual C++ +although the procedure may be similar with other compilers. +</p> + +<H3><a name="Perl5_nn12"></a>28.3.1 Running SWIG from Developer Studio</H3> + + +<p> +If you are developing your application within Microsoft developer +studio, SWIG can be invoked as a custom build option. The process +roughly requires these steps :</p> + +<ul> +<li>Open up a new workspace and use the AppWizard to select a DLL +project. + +<li>Add both the SWIG interface file (the .i file), any supporting C +files, and the name of the wrapper file that will be created by SWIG +(ie. <tt>example_wrap.c</tt>). Note : If using C++, choose a +different suffix for the wrapper file such as +<tt>example_wrap.cxx</tt>. Don't worry if the wrapper file doesn't +exist yet--Developer studio will keep a reference to it around. + +<li>Select the SWIG interface file and go to the settings menu. Under +settings, select the "Custom Build" option. + +<li>Enter "SWIG" in the description field. + +<li>Enter "<tt>swig -perl5 -o $(ProjDir)\$(InputName)_wrap.cxx +$(InputPath)</tt>" in the "Build command(s) field" + +<li>Enter "<tt>$(ProjDir)\$(InputName)_wrap.c</tt>xx" in the "Output +files(s) field". + +<li>Next, select the settings for the entire project and go to +"C++:Preprocessor". Add the include directories for your Perl 5 +installation under "Additional include directories". + +<li>Define the symbols WIN32 and MSWIN32 under preprocessor options. +If using the ActiveWare port, also define the symbol PERL_OBJECT. +Note that all extensions to the ActiveWare port must be compiled with +the C++ compiler since Perl has been encapsulated in a C++ class. + +<li>Finally, select the settings for the entire project and go to +"Link Options". Add the Perl library file to your link libraries. +For example "perl.lib". Also, set the name of the output file to +match the name of your Perl module (ie. example.dll). + +<li>Build your project. +</ul> + +<p> +Now, assuming you made it this far, SWIG will be automatically invoked when +you build your project. Any changes made to the interface file will +result in SWIG being automatically invoked to produce a new version of +the wrapper file. To run your new Perl extension, simply run Perl and +use the use command as normal. For example : +</p> + +<div class="targetlang"><pre> +DOS > perl +use example; +$a = example::fact(4); +print "$a\n"; + +</pre></div> + +<H3><a name="Perl5_nn13"></a>28.3.2 Using other compilers</H3> + + +<p> +SWIG is known to work with Cygwin and may work with other compilers on Windows. +For general hints and suggestions refer to the <a href="Windows.html#Windows">Windows</a> chapter. +</p> + +<H2><a name="Perl5_nn14"></a>28.4 The low-level interface</H2> + + +<p> +At its core, the Perl module uses a simple low-level interface +to C function, variables, constants, and classes. This low-level interface +can be used to control your application. However, it is also used to +construct more user-friendly proxy classes as described in the next section. +</p> + +<H3><a name="Perl5_nn15"></a>28.4.1 Functions</H3> + + +<p> +C functions are converted into new Perl built-in commands (or +subroutines). For example: +</p> + +<div class="targetlang"><pre> +%module example +int fact(int a); +... +</pre></div> + +<p> +Now, in Perl: +</p> + +<div class="targetlang"><pre> +use example; +$a = &example::fact(2); +</pre></div> + +<H3><a name="Perl5_nn16"></a>28.4.2 Global variables</H3> + + +<p> +Global variables are handled using Perl's magic +variable mechanism. SWIG generates a pair of functions +that intercept read/write operations and attaches them to a Perl variable with +the same name as the C global variable. Thus, an interface like this </p> + +<div class="targetlang"><pre> +%module example; +... +double Spam; +... +</pre></div> + +<p> +is accessed as follows :</p> + +<div class="targetlang"><pre> +use example; +print $example::Spam,"\n"; +$example::Spam = $example::Spam + 4 +# ... etc ... + +</pre></div> + +<p> +If a variable is declared as <tt>const</tt>, it is wrapped as a +read-only variable. Attempts to modify its value will result in an +error. +</p> + +<p> +To make ordinary variables read-only, you can also use the <tt>%immutable</tt> directive. For example: +</p> + +<div class="code"> +<pre> +%{ +extern char *path; +%} +%immutable; +extern char *path; +%mutable; +</pre> +</div> + +<p> +The <tt>%immutable</tt> directive stays in effect until it is explicitly disabled or cleared using +<tt>%mutable</tt>. +See the <a href="SWIG.html#SWIG_readonly_variables">Creating read-only variables</a> section for further details. +</p> + +<p> +It is also possible to tag a specific variable as read-only like this: +</p> + +<div class="code"> +<pre> +%{ +extern char *path; +%} +%immutable path; +... +... +extern char *path; // Declared later in the input +</pre> +</div> + +<H3><a name="Perl5_nn17"></a>28.4.3 Constants</H3> + + +<p> +By default, constants are wrapped as read-only Perl variables. For example: +</p> + +<div class="code"> +<pre> +%module example + +#define FOO 42 +</pre> +</div> + +<p> +In Perl: +</p> + +<div class="targetlang"> +<pre> +use example; +print $example::FOO,"\n"; # OK +$example::FOO = 2; # Error +</pre> +</div> + +<p> +Alternatively, if you use swig's <tt>-const</tt> option, constants are wrapped +such that the leading $ isn't required (by using a constant subroutine), which +usually gives a more natural Perl interface, for example: +</p> + +<div class="targetlang"> +<pre> +use example; +print example::FOO,"\n"; +</pre> +</div> + +<H3><a name="Perl5_nn18"></a>28.4.4 Pointers</H3> + + +<p> +SWIG represents pointers as blessed references. A blessed reference +is the same as a Perl reference except that it has additional +information attached to it indicating what kind of reference it +is. That is, if you have a C declaration like this :</p> + +<div class="code"><pre> +Matrix *new_Matrix(int n, int m); +</pre></div> + +<p> +The module returns a value generated as follows: +</p> + +<div class="targetlang"><pre> +$ptr = new_Matrix(int n, int m); # Save pointer return result +bless $ptr, "p_Matrix"; # Bless it as a pointer to Matrix +</pre></div> + +<p> +SWIG uses the "blessing" to check the datatype of various pointers. +In the event of a mismatch, an error or warning message is +generated.</p> + +<p> +To check to see if a value is the NULL pointer, use the +<tt>defined()</tt> command :</p> + +<div class="targetlang"><pre> +if (defined($ptr)) { + print "Not a NULL pointer."; +} else { + print "Is a NULL pointer."; +} + +</pre></div> + +<p> +To create a NULL pointer, you should pass the <tt>undef</tt> value to +a function. +</p> + +<p> +The "value" of a Perl reference is not the same as the underlying C +pointer that SWIG wrapper functions return. Suppose that <tt>$a</tt> +and <tt>$b</tt> are two references that point to the same C object. +In general, <tt>$a</tt> and <tt>$b</tt> will be different--since they +are different references. Thus, it is a mistake to check the equality +of <tt>$a</tt> and <tt>$b</tt> to check the equality of two C +pointers. The correct method to check equality of C pointers is to +dereference them as follows : +</p> + +<div class="targetlang"><pre> +if ($$a == $$b) { + print "a and b point to the same thing in C"; +} else { + print "a and b point to different objects."; +} + +</pre></div> + +<p> +As much as you might be inclined to modify a pointer value directly +from Perl, don't. Manipulating pointer values is architecture dependent and +could cause your program to crash. Similarly, don't try to manually cast +a pointer to a new type by reblessing a pointer. This +may not work like you expect and it is particularly dangerous when +casting C++ objects. If you need to cast a pointer or +change its value, consider writing some helper functions instead. For +example: +</p> + +<div class="code"> +<pre> +%inline %{ +/* C-style cast */ +Bar *FooToBar(Foo *f) { + return (Bar *) f; +} + +/* C++-style cast */ +Foo *BarToFoo(Bar *b) { + return dynamic_cast<Foo*>(b); +} + +Foo *IncrFoo(Foo *f, int i) { + return f+i; +} +%} +</pre> +</div> + +<p> +Also, if working with C++, you should always try +to use the new C++ style casts. For example, in the above code, the +C-style cast may return a bogus result whereas as the C++-style cast will return +<tt>NULL</tt> if the conversion can't be performed. +</p> + +<p> +<b>Compatibility Note:</b> In earlier versions, SWIG tried to preserve the same pointer naming conventions +as XS and <tt>xsubpp</tt>. Given the advancement of the SWIG typesystem and the growing differences between +SWIG and XS, this is no longer supported. +</p> + +<H3><a name="Perl5_nn19"></a>28.4.5 Structures</H3> + + +<p> +Access to the contents of a structure are provided through a set of low-level +accessor functions as described in the "SWIG Basics" chapter. For example, +</p> + +<div class="code"><pre> +struct Vector { + double x,y,z; +}; +</pre></div> + +<p> +gets mapped into the following collection of accessor functions: +</p> + +<div class="code"><pre> +struct Vector *new_Vector(); +void delete_Vector(Vector *v); +double Vector_x_get(Vector *obj) +void Vector_x_set(Vector *obj, double x) +double Vector_y_get(Vector *obj) +void Vector_y_set(Vector *obj, double y) +double Vector_z_get(Vector *obj) +void Vector_z_set(Vector *obj, double z) + +</pre></div> + +<p> +These functions are then used to access structure data from Perl as follows: +</p> + +<div class="targetlang"><pre> +$v = example::new_Vector(); +print example::Vector_x_get($v),"\n"; # Get x component +example::Vector_x_set($v,7.8); # Change x component +</pre></div> + +<p> +Similar access is provided for unions and the data members of C++ classes. +</p> + +<p> +<tt>const</tt> members of a structure are read-only. Data members +can also be forced to be read-only using the <tt>%immutable</tt> directive. For example: +</p> + +<div class="code"> +<pre> +struct Foo { + ... + %immutable; + int x; /* Read-only members */ + char *name; + %mutable; + ... +}; +</pre> +</div> + +<p> +When <tt>char *</tt> members of a structure are wrapped, the contents are assumed to be +dynamically allocated using <tt>malloc</tt> or <tt>new</tt> (depending on whether or not +SWIG is run with the -c++ option). When the structure member is set, the old contents will be +released and a new value created. If this is not the behavior you want, you will have to use +a typemap (described later). +</p> + +<p> +Array members are normally wrapped as read-only. For example, +</p> + +<div class="code"> +<pre> +struct Foo { + int x[50]; +}; +</pre> +</div> + +<p> +produces a single accessor function like this: +</p> + +<div class="code"> +<pre> +int *Foo_x_get(Foo *self) { + return self->x; +}; +</pre> +</div> + +<p> +If you want to set an array member, you will need to supply a "memberin" typemap +described later in this chapter. As a special case, SWIG does generate +code to set array members of type <tt>char</tt> (allowing you to store a Python +string in the structure). +</p> + +<p> +When structure members are wrapped, they are handled as pointers. For example, +</p> + +<div class="code"> +<pre> +struct Foo { + ... +}; + +struct Bar { + Foo f; +}; +</pre> +</div> + +<p> +generates accessor functions such as this: +</p> + +<div class="code"> +<pre> +Foo *Bar_f_get(Bar *b) { + return &b->f; +} + +void Bar_f_set(Bar *b, Foo *val) { + b->f = *val; +} +</pre> +</div> + + +<H3><a name="Perl5_nn20"></a>28.4.6 C++ classes</H3> + + +<p> +C++ classes are wrapped by building a set of low level accessor functions. +Consider the following class : +</p> + +<div class="code"><pre> +class List { +public: + List(); + ~List(); + int search(char *item); + void insert(char *item); + void remove(char *item); + char *get(int n); + int length; +static void print(List *l); +}; +</pre></div> + +<p> +When wrapped by SWIG, the following functions are created : +</p> + +<div class="code"><pre> +List *new_List(); +void delete_List(List *l); +int List_search(List *l, char *item); +void List_insert(List *l, char *item); +void List_remove(List *l, char *item); +char *List_get(List *l, int n); +int List_length_get(List *l); +void List_length_set(List *l, int n); +void List_print(List *l); + +</pre></div> + +<p> +In Perl, these functions are used in a straightforward manner: +</p> + +<div class="targetlang"><pre> +use example; +$l = example::new_List(); +example::List_insert($l,"Ale"); +example::List_insert($l,"Stout"); +example::List_insert($l,"Lager") +example::List_print($l) +Lager +Stout +Ale +print example::List_length_get($l),"\n"; +3 +</pre></div> + +<p> +At this low level, C++ objects are really just typed pointers. Member +functions are accessed by calling a C-like wrapper with an instance pointer +as the first argument. Although this interface is fairly primitive, it +provides direct access to C++ objects. A higher level interface using Perl proxy classes +can be built using these low-level accessors. This is described shortly. +</p> + +<H3><a name="Perl5_nn21"></a>28.4.7 C++ classes and type-checking</H3> + + +<p> +The SWIG type-checker is fully aware of C++ inheritance. Therefore, if you have +classes like this +</p> + +<div class="code"> +<pre> +class Foo { +... +}; + +class Bar : public Foo { +... +}; +</pre> +</div> + +<p> +and a function +</p> + +<div class="code"> +<pre> +void spam(Foo *f); +</pre> +</div> + +<p> +then the function <tt>spam()</tt> accepts <tt>Foo *</tt> or a pointer to any class derived from <tt>Foo</tt>. +If necessary, the type-checker also adjusts the value of the pointer (as is necessary when +multiple inheritance is used). +</p> + +<H3><a name="Perl5_nn22"></a>28.4.8 C++ overloaded functions</H3> + + +<p> +If you have a C++ program with overloaded functions or methods, you will need to disambiguate +those methods using <tt>%rename</tt>. For example: +</p> + +<div class="code"> +<pre> +/* Forward renaming declarations */ +%rename(foo_i) foo(int); +%rename(foo_d) foo(double); +... +void foo(int); // Becomes 'foo_i' +void foo(char *c); // Stays 'foo' (not renamed) + +class Spam { +public: + void foo(int); // Becomes 'foo_i' + void foo(double); // Becomes 'foo_d' + ... +}; +</pre> +</div> + +<p> +Now, in Perl, the methods are accessed as follows: +</p> + +<div class="targetlang"> +<pre> +use example; +example::foo_i(3); +$s = example::new_Spam(); +example::Spam_foo_i($s,3); +example::Spam_foo_d($s,3.14); +</pre> +</div> + +<p> +Please refer to the "SWIG Basics" chapter for more information. +</p> + +<H3><a name="Perl5_nn23"></a>28.4.9 Operators</H3> + + + <p> +As of version 1.3.27 SWIG automatically renames the most common C++ operators, and maps them into the perl module with the proper 'use overload ...' so you don't need to do any work. + </p> + + <p> +The following C++ operators are currently supported by the Perl module: + </p> + + <ul> +<li>operator++ </li> +<li>operator-- </li> +<li>operator+ </li> +<li>operator- </li> +<li>operator* </li> +<li>operator/ </li> +<li>operator== </li> +<li>operator!= </li> +<li>operator% </li> +<li>operator> </li> +<li>operator< </li> +<li>operator and </li> +<li>operator or </li> + </ul> + +<H3><a name="Perl5_nn24"></a>28.4.10 Modules and packages</H3> + + +<p> +When you create a SWIG extension, everything gets placed into +a single Perl module. The name of the module is determined by the +<tt>%module</tt> directive. To use the module, do the following : +</p> + +<div class="targetlang"><pre> +% perl5 +use example; # load the example module +print example::fact(4),"\n" # Call a function in it +24 +</pre></div> + +<p> +Usually, a module consists of a collection of code that is contained +within a single file. A package, on the other hand, is the Perl +equivalent of a namespace. A package is a lot like a module, except +that it is independent of files. Any number of files may be part of +the same package--or a package may be broken up into a collection of +modules if you prefer to think about it in this way. +</p> + +<p> +SWIG installs its functions into a package with the same name as +the module. </p> + +<p> +<b>Incompatible Change:</b> previous versions of SWIG enabled you to +change the name of the package by using the -package option, this +feature has been removed in order to properly support modules that +used nested namespaces, e.g. Foo::Bar::Baz. To give your module a +nested namespace simply provide the fully qualified name in your +%module directive: </p> + +<div class="code"><pre> +%module "Foo::Bar::Baz" +</pre></div> + +<p> +<b>NOTE:</b> the double quotes are necessary. +</p> + +<p> + Using the <tt>package</tt> option of the <tt>%module</tt> directive allows + you to specify what Perl namespace that the module will be living in when + installed. This is useful in the situation where a module maintainer + wants to split a large module into smaller pieces to make maintenance + easier, but doesn't want to have that affect the module name used by + applications. So for example, if I wanted to split <tt>XML::Xerces</tt> + into <tt>XML::Xerces::SAX</tt>, etc. , but I wanted all the applications + to be able to access the classes using the <tt>XML::Xerces</tt> namespace + I could use: + +</p> + +<div class="code"> +<pre> +%module(package="XML::Xerces") "XML::Xerces::SAX +</pre> +</div> + +<p> + And now all the applications could use the class + <tt>XML::Xerces::SAXParser</tt>. Without the <tt>package</tt> directive + splitting the module would force applications to use the class + <tt>XML::Xerces::SAX::SAXParser</tt>. This could break compatibility for + existing applications that are already using the class under the name + <tt>XML::Xerces::SAXParser</tt>. + </p> + +<!-- +<p> +This can be changed by giving SWIG the -package +option : +</p> + +<div class="code"><pre> +% swig -perl -package Foo example.i +</pre></div> + +<p> +In this case, you still create a module called `<tt>example</tt>' exactly as before, but +all of the functions in that module will be installed into the package +`<tt>Foo</tt>.' For example : +</p> + +<div class="targetlang"><pre> +use example; # Load the module like before +print Foo::fact(4),"\n"; # Call a function in package FooBar +</pre></div> +--> + +<H2><a name="Perl5_nn25"></a>28.5 Input and output parameters</H2> + + +<p> +A common problem in some C programs is handling parameters passed as simple pointers. For +example: +</p> + +<div class="code"> +<pre> +void add(int x, int y, int *result) { + *result = x + y; +} +</pre> +</div> + +<p> +or perhaps +</p> + +<div class="code"> +<pre> +int sub(int *x, int *y) { + return *x+*y; +} +</pre> +</div> + +<p> +The easiest way to handle these situations is to use the <tt>typemaps.i</tt> file. For example: +</p> + +<div class="code"> +<pre> +%module example +%include "typemaps.i" + +void add(int, int, int *OUTPUT); +int sub(int *INPUT, int *INPUT); +</pre> +</div> + +<p> +In Perl, this allows you to pass simple values. For example: +</p> + +<div class="targetlang"> +<pre> +$a = example::add(3,4); +print "$a\n"; +7 +$b = example::sub(7,4); +print "$b\n"; +3 +</pre> +</div> + +<p> +Notice how the <tt>INPUT</tt> parameters allow integer values to be passed instead of pointers +and how the <tt>OUTPUT</tt> parameter creates a return result. +</p> + +<p> +If you don't want to use the names <tt>INPUT</tt> or <tt>OUTPUT</tt>, use the <tt>%apply</tt> +directive. For example: +</p> + +<div class="code"> +<pre> +%module example +%include "typemaps.i" + +%apply int *OUTPUT { int *result }; +%apply int *INPUT { int *x, int *y}; + +void add(int x, int y, int *result); +int sub(int *x, int *y); +</pre> +</div> + +<p> +If a function mutates one of its parameters like this, +</p> + +<div class="code"> +<pre> +void negate(int *x) { + *x = -(*x); +} +</pre> +</div> + +<p> +you can use <tt>INOUT</tt> like this: +</p> + +<div class="code"> +<pre> +%include "typemaps.i" +... +void negate(int *INOUT); +</pre> +</div> + +<p> +In Perl, a mutated parameter shows up as a return value. For example: +</p> + +<div class="targetlang"> +<pre> +$a = example::negate(3); +print "$a\n"; +-3 +</pre> +</div> + +<p> +The most common use of these special typemap rules is to handle functions that +return more than one value. For example, sometimes a function returns a result +as well as a special error code: +</p> + +<div class="code"> +<pre> +/* send message, return number of bytes sent, along with success code */ +int send_message(char *text, int len, int *success); +</pre> +</div> + +<p> +To wrap such a function, simply use the <tt>OUTPUT</tt> rule above. For example: +</p> + +<div class="code"> +<pre> +%module example +%include "typemaps.i" +%apply int *OUTPUT { int *success }; +... +int send_message(char *text, int *success); +</pre> +</div> + +<p> +When used in Perl, the function will return multiple values. +</p> + +<div class="targetlang"> +<pre> +($bytes, $success) = example::send_message("Hello World"); +</pre> +</div> + +<p> +Another common use of multiple return values are in query functions. For example: +</p> + +<div class="code"> +<pre> +void get_dimensions(Matrix *m, int *rows, int *columns); +</pre> +</div> + +<p> +To wrap this, you might use the following: +</p> + +<div class="code"> +<pre> +%module example +%include "typemaps.i" +%apply int *OUTPUT { int *rows, int *columns }; +... +void get_dimensions(Matrix *m, int *rows, *columns); +</pre> +</div> + +<p> +Now, in Perl: +</p> + +<div class="targetlang"> +<pre> +($r,$c) = example::get_dimensions($m); +</pre> +</div> + +<p> +In certain cases, it is possible to treat Perl references as C pointers. To do this, use the <tt>REFERENCE</tt> typemap. For +example: +</p> + +<div class="code"> +<pre> +%module example +%include "typemaps.i" + +void add(int x, int y, int *REFERENCE); +</pre> +</div> + +<p> +In Perl: +</p> + +<div class="targetlang"> +<pre> +use example; +$c = 0.0; +example::add(3,4,\$c); +print "$c\n"; +7 +</pre> +</div> + +<p> +<b>Note:</b> The <tt>REFERENCE</tt> feature is only currently supported for numeric types (integers and floating point). +</p> + +<H2><a name="Perl5_nn26"></a>28.6 Exception handling</H2> + + +<p> +The SWIG <tt>%exception</tt> directive can be used to create a +user-definable exception handler for converting exceptions in your +C/C++ program into Perl exceptions. The chapter on customization features +contains more details, but suppose you have a C++ class like the +following : +</p> + +<div class="code"><pre> +class RangeError {}; // Used for an exception + +class DoubleArray { + private: + int n; + double *ptr; + public: + // Create a new array of fixed size + DoubleArray(int size) { + ptr = new double[size]; + n = size; + } + // Destroy an array + ~DoubleArray() { + delete ptr; + } + // Return the length of the array + int length() { + return n; + } + + // Get an item from the array and perform bounds checking. + double getitem(int i) { + if ((i >= 0) && (i < n)) + return ptr[i]; + else + throw RangeError(); + } + + // Set an item in the array and perform bounds checking. + void setitem(int i, double val) { + if ((i >= 0) && (i < n)) + ptr[i] = val; + else { + throw RangeError(); + } + } + }; +</pre></div> + +<p> +Since several methods in this class can throw an exception +for an out-of-bounds access, you might want to catch +this in the Perl extension by writing the following in an +interface file: +</p> + +<div class="code"><pre> +%exception { + try { + $action + } + catch (RangeError) { + croak("Array index out-of-bounds"); + } +} + +class DoubleArray { +... +}; +</pre></div> + +<p> +The exception handling code is inserted directly into generated wrapper +functions. The <tt>$action</tt> variable is replaced with the C/C++ +code being executed by the wrapper. When an exception handler +is defined, errors can be caught and used to gracefully generate a Perl error +instead of forcing the entire program to terminate with an uncaught error. +</p> + +<p> +As shown, the exception handling code will be added to every wrapper function. +Since this is somewhat inefficient. You might consider refining the +exception handler to only apply to specific methods like this: +</p> + +<div class="code"> +<pre> +%exception getitem { + try { + $action + } + catch (RangeError) { + croak("Array index out-of-bounds"); + } +} + +%exception setitem { + try { + $action + } + catch (RangeError) { + croak("Array index out-of-bounds"); + } +} +</pre> +</div> + +<p> +In this case, the exception handler is only attached to methods and functions +named <tt>getitem</tt> and <tt>setitem</tt>. +</p> + +<p> +If you had a lot of different methods, you can avoid extra typing by using a macro. +For example: +</p> + +<div class="code"> +<pre> +%define RANGE_ERROR +{ + try { + $action + } + catch (RangeError) { + croak("Array index out-of-bounds"); + } +} +%enddef + +%exception getitem RANGE_ERROR; +%exception setitem RANGE_ERROR; +</pre> +</div> + +<p> +Since SWIG's exception handling is user-definable, you are not limited to C++ exception handling. +See the chapter on "<a href="Customization.html#Customization">Customization features</a>" for more examples. +</p> + +<p> +<b>Compatibility note:</b> In SWIG1.1, exceptions were defined using the older <tt>%except</tt> directive: +</p> + +<div class="code"> +<pre> +%except(python) { + try { + $function + } + catch (RangeError) { + croak("Array index out-of-bounds"); + } +} +</pre> +</div> + +<p> +This is still supported, but it is deprecated. The newer <tt>%exception</tt> directive provides the same +functionality, but it has additional capabilities that make it more powerful. +</p> + +<H2><a name="Perl5_nn27"></a>28.7 Remapping datatypes with typemaps</H2> + + +<p> +This section describes how you can modify SWIG's default wrapping behavior +for various C/C++ datatypes using the <tt>%typemap</tt> directive. This +is an advanced topic that assumes familiarity with the Perl C API as well +as the material in the "<a href="Typemaps.html#Typemaps">Typemaps</a>" chapter. +</p> + +<p> +Before proceeding, it should be stressed that typemaps are <em>not</em> a required +part of using SWIG---the default wrapping behavior is enough in most cases. +Typemaps are only used if you want to change some aspect of the primitive +C-Perl interface. +</p> + +<H3><a name="Perl5_nn28"></a>28.7.1 A simple typemap example</H3> + + +<p> +A typemap is nothing more than a code generation rule that is attached to +a specific C datatype. For example, to convert integers from Perl to C, +you might define a typemap like this: +</p> + +<div class="code"><pre> +%module example + +%typemap(in) int { + $1 = (int) SvIV($input); + printf("Received an integer : %d\n", $1); +} +... +%inline %{ +extern int fact(int n); +%} + +</pre></div> + +<p> +Typemaps are always associated with some specific aspect of code generation. +In this case, the "in" method refers to the conversion of input arguments +to C/C++. The datatype <tt>int</tt> is the datatype to which the typemap +will be applied. The supplied C code is used to convert values. In this +code a number of special variable prefaced by a <tt>$</tt> are used. The +<tt>$1</tt> variable is placeholder for a local variable of type <tt>int</tt>. +The <tt>$input</tt> variable is the input object (usually a <tt>SV *</tt>). +</p> + +<p> +When this example is used in Perl5, it will operate as follows : +</p> + +<div class="targetlang"><pre> +use example; +$n = example::fact(6); +print "$n\n"; +... + +Output : +Received an integer : 6 +720 +</pre></div> + +<p> +The application of a typemap to specific datatypes and argument names involves +more than simple text-matching--typemaps are fully integrated into the +SWIG type-system. When you define a typemap for <tt>int</tt>, that typemap +applies to <tt>int</tt> and qualified variations such as <tt>const int</tt>. In addition, +the typemap system follows <tt>typedef</tt> declarations. For example: +</p> + +<div class="targetlang"> +<pre> +%typemap(in) int n { + $1 = (int) SvIV($input); + printf("n = %d\n",$1); +} +%inline %{ +typedef int Integer; +extern int fact(Integer n); // Above typemap is applied +%} +</pre> +</div> + +<p> +It should be noted that the matching of <tt>typedef</tt> only occurs in one direction. If you +defined a typemap for <tt>Integer</tt>, it is not applied to arguments of +type <tt>int</tt>. +</p> + +<p> +Typemaps can also be defined for groups of consecutive arguments. For example: +</p> + +<div class="targetlang"> +<pre> +%typemap(in) (char *str, unsigned len) { + $1 = SvPV($input,$2); +}; + +int count(char c, char *str, unsigned len); +</pre> +</div> + +<p> +When a multi-argument typemap is defined, the arguments are always handled as a single +Perl object. This allows the function to be used like this (notice how the length +parameter is omitted): +</p> + +<div class="targetlang"> +<pre> +example::count("e","Hello World"); +1 +>>> +</pre> +</div> + + +<H3><a name="Perl5_nn29"></a>28.7.2 Perl5 typemaps</H3> + + +<p> +The previous section illustrated an "in" typemap for converting Perl objects to C. +A variety of different typemap methods are defined by the Perl module. For example, +to convert a C integer back into a Perl object, you might define an "out" typemap +like this: +</p> + + +<div class="targetlang"> +<pre> +%typemap(out) int { + $result = sv_newmortal(); + set_setiv($result, (IV) $1); + argvi++; +} +</pre> +</div> + +<p> +The following typemap methods are available: +</p> + +<p> +<tt>%typemap(in)</tt> +</p> + +<div class="indent"> +Converts Perl5 object to input function arguments. +</div> + +<p> +<tt>%typemap(out)</tt> +</p> + +<div class="indent"> +Converts function return value to a Perl5 value. +</div> + +<p> +<tt>%typemap(varin)</tt> +</p> + +<div class="indent"> +Converts a Perl5 object to a global variable. +</div> + +<p> +<tt>%typemap(varout)</tt> +</p> + +<div class="indent"> +Converts a global variable to a Perl5 object. +</div> + +<p> +<tt>%typemap(freearg)</tt> +</p> + +<div class="indent"> +Cleans up a function argument after a function call +</div> + +<p> +<tt>%typemap(argout)</tt> +</p> + +<div class="indent"> +Output argument handling +</div> + +<p> +<tt>%typemap(ret)</tt> +</p> + +<div class="indent"> +Clean up return value from a function. +</div> + +<p> +<tt>%typemap(memberin)</tt> +</p> + +<div class="indent"> +Setting of C++ member data (all languages). +</div> + +<p> +<tt>%typemap(memberout)</tt> +</p> + +<div class="indent"> +Return of C++ member data (all languages). +</div> + +<p> +<tt>%typemap(check)</tt> +</p> + +<div class="indent"> +Check value of input parameter. +</div> + +<H3><a name="Perl5_nn30"></a>28.7.3 Typemap variables</H3> + + +<p> +Within typemap code, a number of special variables prefaced with a <tt>$</tt> may appear. +A full list of variables can be found in the "<a href="Typemaps.html#Typemaps">Typemaps</a>" chapter. +This is a list of the most common variables: +</p> + +<p> +<tt>$1</tt> +</p> + +<div class="indent"> +A C local variable corresponding to the actual type specified in the +<tt>%typemap</tt> directive. For input values, this is a C local variable +that's supposed to hold an argument value. For output values, this is +the raw result that's supposed to be returned to Perl. +</div> + +<p> +<tt>$input</tt> +</p> + +<div class="indent"> +A Perl object holding the value of an argument of variable value. +</div> + +<p> +<tt>$result</tt> +</p> + +<div class="indent"> +A Perl object that holds the result to be returned to Perl. +</div> + +<p> +<tt>$1_name</tt> +</p> + +<div class="indent"> +The parameter name that was matched. +</div> + +<p> +<tt>$1_type</tt> +</p> + +<div class="indent"> +The actual C datatype matched by the typemap. +</div> + +<p> +<tt>$1_ltype</tt> +</p> + +<div class="indent"> +An assignable version of the datatype matched by the typemap (a type that can appear on the left-hand-side of +a C assignment operation). This type is stripped of qualifiers and may be an altered version of <tt>$1_type</tt>. +All arguments and local variables in wrapper functions are declared using this type so that their values can be +properly assigned. +</div> + +<p> +<tt>$symname</tt> +</p> + +<div class="indent"> +The Perl name of the wrapper function being created. +</div> + +<H3><a name="Perl5_nn31"></a>28.7.4 Useful functions</H3> + + +<p> +When writing typemaps, it is necessary to work directly with Perl5 +objects. This, unfortunately, can be a daunting task. Consult the +"perlguts" man-page for all of the really ugly details. A short +summary of commonly used functions is provided here for reference. It +should be stressed that SWIG can be used quite effectively without +knowing any of these details--especially now that there are typemap +libraries that can already been written. +</p> + +<p> +<b>Perl Integer Functions</b> +</p> + +<div class="code"> +<pre> +int SvIV(SV *); +void sv_setiv(SV *sv, IV value); +SV *newSViv(IV value); +int SvIOK(SV *); +</pre> +</div> + +<p> +<b>Perl Floating Point Functions</b> +</p> + +<div class="code"> +<pre> +double SvNV(SV *); +void sv_setnv(SV *, double value); +SV *newSVnv(double value); +int SvNOK(SV *); +</pre> +</div> + +<p> +<b>Perl String Functions</b> +</p> + +<div class="code"> +<pre> +char *SvPV(SV *, STRLEN len); +void sv_setpv(SV *, char *val); +void sv_setpvn(SV *, char *val, STRLEN len); +SV *newSVpv(char *value, STRLEN len); +int SvPOK(SV *); +void sv_catpv(SV *, char *); +void sv_catpvn(SV *, char *, STRLEN); +</pre> +</div> + +<p> +<b>Perl References</b> +</p> + +<div class="code"> +<pre> +void sv_setref_pv(SV *, char *, void *ptr); +int sv_isobject(SV *); +SV *SvRV(SV *); +int sv_isa(SV *, char *0; +</pre> +</div> + + +<H2><a name="Perl5_nn32"></a>28.8 Typemap Examples</H2> + + +<p> +This section includes a few examples of typemaps. For more examples, you +might look at the files "<tt>perl5.swg</tt>" and "<tt>typemaps.i</tt>" in +the SWIG library. +</p> + +<H3><a name="Perl5_nn33"></a>28.8.1 Converting a Perl5 array to a char **</H3> + + +<p> +A common problem in many C programs is the processing of command line +arguments, which are usually passed in an array of NULL terminated +strings. The following SWIG interface file allows a Perl5 array +reference to be used as a char ** datatype. +</p> + +<div class="code"><pre> +%module argv + +// This tells SWIG to treat char ** as a special case +%typemap(in) char ** { + AV *tempav; + I32 len; + int i; + SV **tv; + if (!SvROK($input)) + croak("Argument $argnum is not a reference."); + if (SvTYPE(SvRV($input)) != SVt_PVAV) + croak("Argument $argnum is not an array."); + tempav = (AV*)SvRV($input); + len = av_len(tempav); + $1 = (char **) malloc((len+2)*sizeof(char *)); + for (i = 0; i <= len; i++) { + tv = av_fetch(tempav, i, 0); + $1[i] = (char *) SvPV(*tv,PL_na); + } + $1[i] = NULL; +}; + +// This cleans up the char ** array after the function call +%typemap(freearg) char ** { + free($1); +} + +// Creates a new Perl array and places a NULL-terminated char ** into it +%typemap(out) char ** { + AV *myav; + SV **svs; + int i = 0,len = 0; + /* Figure out how many elements we have */ + while ($1[len]) + len++; + svs = (SV **) malloc(len*sizeof(SV *)); + for (i = 0; i < len ; i++) { + svs[i] = sv_newmortal(); + sv_setpv((SV*)svs[i],$1[i]); + }; + myav = av_make(len,svs); + free(svs); + $result = newRV_noinc((SV*)myav); + sv_2mortal($result); + argvi++; +} + +// Now a few test functions +%inline %{ +int print_args(char **argv) { + int i = 0; + while (argv[i]) { + printf("argv[%d] = %s\n", i,argv[i]); + i++; + } + return i; +} + +// Returns a char ** list +char **get_args() { + static char *values[] = { "Dave", "Mike", "Susan", "John", "Michelle", 0}; + return &values[0]; +} +%} + +</pre></div> + +<p> +When this module is compiled, the wrapped C functions can be used in a +Perl script as follows : +</p> + +<div class="targetlang"><pre> +use argv; +@a = ("Dave", "Mike", "John", "Mary"); # Create an array of strings +argv::print_args(\@a); # Pass it to our C function +$b = argv::get_args(); # Get array of strings from C +print @$b,"\n"; # Print it out +</pre></div> + + +<H3><a name="Perl5_nn34"></a>28.8.2 Return values</H3> + + +<p> +Return values are placed on the argument stack of each wrapper +function. The current value of the argument stack pointer is +contained in a variable <tt>argvi</tt>. Whenever a new output value +is added, it is critical that this value be incremented. For multiple +output values, the final value of <tt>argvi</tt> should be the total +number of output values. +</p> + +<p> +The total number of return values should not exceed the number of +input values unless you explicitly extend the argument stack. This +can be done using the <tt>EXTEND()</tt> macro as in : +</p> + +<div class="code"><pre> +%typemap(argout) int *OUTPUT { + if (argvi >= items) { + EXTEND(sp,1); /* Extend the stack by 1 object */ + } + $result = sv_newmortal(); + sv_setiv($target,(IV) *($1)); + argvi++; +} +</pre></div> + +<H3><a name="Perl5_nn35"></a>28.8.3 Returning values from arguments</H3> + + +<p> +Sometimes it is desirable for a function to return a value in one of +its arguments. This example describes the implementation of the <tt>OUTPUT</tt> typemap. +</p> + +<div class="code"><pre> +%module return + +// This tells SWIG to treat an double * argument with name 'OutDouble' as +// an output value. + +%typemap(argout) double *OUTPUT { + $result = sv_newmortal(); + sv_setnv($result, *$input); + argvi++; /* Increment return count -- important! */ +} + +// We don't care what the input value is. Ignore, but set to a temporary variable + +%typemap(in,numinputs=0) double *OUTPUT(double junk) { + $1 = &junk; +} + +// Now a function to test it +%{ +/* Returns the first two input arguments */ +int multout(double a, double b, double *out1, double *out2) { + *out1 = a; + *out2 = b; + return 0; +}; +%} + +// If we name both parameters OutDouble both will be output + +int multout(double a, double b, double *OUTPUT, double *OUTPUT); +... +</pre></div> + +<p> +When this function is called, the output arguments are appended to the stack used +to return results. This shows up an array in Perl. +For example : +</p> + +<div class="targetlang"><pre> +@r = multout(7,13); +print "multout(7,13) = @r\n"; +($x,$y) = multout(7,13); +</pre></div> + +<H3><a name="Perl5_nn36"></a>28.8.4 Accessing array structure members</H3> + + +<p> +Consider the following data structure : +</p> + +<div class="code"><pre> +#define SIZE 8 +typedef struct { + int values[SIZE]; + ... +} Foo; + +</pre></div> + +<p> +By default, SWIG doesn't know how to the handle the values structure +member it's an array, not a pointer. In this case, SWIG makes the array member +read-only. Reading will simply return a pointer to the first item in the array. +To make the member writable, a "memberin" typemap can be used. +</p> + +<div class="code"><pre> +%typemap(memberin) int [SIZE] { + int i; + for (i = 0; i < SIZE; i++) { + $1[i] = $input[i]; + } +} + +</pre></div> + +<p> +Whenever a <tt>int [SIZE]</tt> member is encountered in a structure +or class, this typemap provides a safe mechanism for setting its +value. +</p> + +<p> +As in the previous example, the typemap can be generalized for any dimension. +For example: +</p> + +<div class="code"><pre> +%typemap(memberin) int [ANY] { + int i; + for (i = 0; i < $1_dim0; i++) { + $1[i] = $input[i]; + } +} +</pre></div> + +<p> +When setting structure members, the input object is always assumed to +be a C array of values that have already been converted from the +target language. Because of this, the <tt>memberin</tt> typemap is +almost always combined with the use of an "in" typemap. For example, +the "in" typemap in the previous section would be used to convert an +<tt>int[]</tt> array to C whereas the "memberin" typemap would be used +to copy the converted array into a C data structure. +</p> + +<H3><a name="Perl5_nn37"></a>28.8.5 Turning Perl references into C pointers</H3> + + +<p> +A frequent confusion on the SWIG mailing list is errors caused by the +mixing of Perl references and C pointers. For example, suppose you +have a C function that modifies its arguments like this : +</p> + +<div class="code"><pre> +void add(double a, double b, double *c) { + *c = a + b; +} +</pre></div> + +<p> +A common misinterpretation of this function is the following Perl script : +</p> + +<div class="targetlang"><pre> +# Perl script +$a = 3.5; +$b = 7.5; +$c = 0.0; # Output value +add($a,$b,\$c); # Place result in c (Except that it doesn't work) +</pre></div> + +<p> +To make this work with a reference, you can use a typemap such as this: +</p> + +<div class="code"><pre> +%typemap(in) double * (double dvalue) { + SV* tempsv; + if (!SvROK($input)) { + croak("expected a reference\n"); + } + tempsv = SvRV($input); + if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) { + croak("expected a double reference\n"); + } + dvalue = SvNV(tempsv); + $1 = &dvalue; +} + +%typemap(argout) double * { + SV *tempsv; + tempsv = SvRV($input); + sv_setnv(tempsv, *$1); +} +</pre></div> + +<p> +Now, if you place this before the add function, you can do this : +</p> + +<div class="targetlang"><pre> +$a = 3.5; +$b = 7.5; +$c = 0.0; +add($a,$b,\$c); # Now it works! +print "$c\n"; + +</pre></div> + +<H3><a name="Perl5_nn38"></a>28.8.6 Pointer handling</H3> + + +<p> +Occasionally, it might be necessary to convert pointer values that have +been stored using the SWIG typed-pointer representation. To convert a pointer from Perl to C, the following +function is used: +</p> + +<p> +<tt> +int SWIG_ConvertPtr(SV *obj, void **ptr, swig_type_info *ty, int flags) +</tt> +</p> + +<div class="indent"> +Converts a Perl object <tt>obj</tt> to a C pointer. The result of the conversion is placed +into the pointer located at <tt>ptr</tt>. <tt>ty</tt> is a SWIG type descriptor structure. +<tt>flags</tt> is used to handle error checking and other aspects of conversion. <tt>flags</tt> is +currently undefined and reserved for future expansion. Returns 0 on success and -1 on error. +</div> + +<p> +<tt> +void *SWIG_MakePtr(SV *obj, void *ptr, swig_type_info *ty, int flags)</tt> +</p> + +<div class="indent"> +Creates a new Perl pointer object. <tt>obj</tt> is a Perl SV that has been initialized to hold the result, +<tt>ptr</tt> is the pointer to convert, <tt>ty</tt> is the SWIG type descriptor structure that +describes the type, and <tt>flags</tt> is a flag that controls properties of the conversion. <tt>flags</tt> is currently undefined +and reserved. +</div> + +<p> +Both of these functions require the use of a special SWIG +type-descriptor structure. This structure contains information about +the mangled name of the datatype, type-equivalence information, as +well as information about converting pointer values under C++ +inheritance. For a type of <tt>Foo *</tt>, the type descriptor structure +is usually accessed as follows: +</p> + +<div class="code"> +<pre> +Foo *f; +if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0) == -1) return NULL; + +SV *sv = sv_newmortal(); +SWIG_MakePtr(sv, f, SWIGTYPE_p_Foo, 0); +</pre> +</div> + +<p> +In a typemap, the type descriptor should always be accessed using the special typemap +variable <tt>$1_descriptor</tt>. For example: +</p> + +<div class="code"> +<pre> +%typemap(in) Foo * { + if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,0)) == -1) return NULL; +} +</pre> +</div> + +<p> +If necessary, the descriptor for any type can be obtained using the <tt>$descriptor()</tt> macro in a typemap. +For example: +</p> + +<div class="code"> +<pre> +%typemap(in) Foo * { + if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 0)) == -1) return NULL; +} +</pre> +</div> + +<H2><a name="Perl5_nn39"></a>28.9 Proxy classes</H2> + + +<p> +<b>Out of date. Needs update.</b> +</p> + +<p> +Using the low-level procedural interface, SWIG can also construct a +high-level object oriented interface to C structures and C++ classes. +This is done by constructing a Perl proxy class (also known as a shadow class) +that provides an OO wrapper +to the underlying code. This section describes the implementation +details of the proxy interface. +</p> + +<H3><a name="Perl5_nn40"></a>28.9.1 Preliminaries</H3> + + +<p> +Proxy classes, are generated by default. If you want to turn them off, use the <tt>-noproxy</tt> command line option. +For example: +</p> + +<div class="code"> +<pre> +$ swig -c++ -perl -noproxy example.i +</pre> +</div> + +<p> +When proxy classes are used, SWIG moves all of the low-level procedural wrappers to +another package name. By default, this package is named 'modulec' where 'module' is the name of the module +you provided with the <tt>%module</tt> directive. Then, in place of the original module, +SWIG creates a collection of high-level Perl wrappers. In your scripts, you will use these +high level wrappers. The wrappers, in turn, interact with the low-level procedural module. +</p> + +<H3><a name="Perl5_nn41"></a>28.9.2 Structure and class wrappers</H3> + + +<p> +Suppose you have the following SWIG interface file : +</p> + +<div class="code"><pre> +%module example +struct Vector { + Vector(double x, double y, double z); + ~Vector(); + double x,y,z; +}; + +</pre></div> + +<p> +When wrapped, SWIG creates the following set of low-level accessor +functions as described in previous sections. +</p> + +<div class="code"><pre> +Vector *new_Vector(double x, double y, double z); +void delete_Vector(Vector *v); +double Vector_x_get(Vector *v); +double Vector_x_set(Vector *v, double value); +double Vector_y_get(Vector *v); +double Vector_y_set(Vector *v, double value); +double Vector_z_get(Vector *v); +double Vector_z_set(Vector *v, double value); + +</pre></div> + +<p> +However, when proxy classes are enabled, these accessor functions are +wrapped inside a Perl class like this: +</p> + +<div class="targetlang"><pre> +package example::Vector; +@ISA = qw( example ); +%OWNER = (); +%BLESSEDMEMBERS = (); + +sub new () { + my $self = shift; + my @args = @_; + $self = vectorc::new_Vector(@args); + return undef if (!defined($self)); + bless $self, "example::Vector"; + $OWNER{$self} = 1; + my %retval; + tie %retval, "example::Vector", $self; + return bless \%retval,"Vector"; +} + +sub DESTROY { + return unless $_[0]->isa('HASH'); + my $self = tied(%{$_[0]}); + delete $ITERATORS{$self}; + if (exists $OWNER{$self}) { + examplec::delete_Vector($self)); + delete $OWNER{$self}; +} + +sub FETCH { + my ($self,$field) = @_; + my $member_func = "vectorc::Vector_${field}_get"; + my $val = &$member_func($self); + if (exists $BLESSEDMEMBERS{$field}) { + return undef if (!defined($val)); + my %retval; + tie %retval,$BLESSEDMEMBERS{$field},$val; + return bless \%retval, $BLESSEDMEMBERS{$field}; + } + return $val; +} + +sub STORE { + my ($self,$field,$newval) = @_; + my $member_func = "vectorc::Vector_${field}_set"; + if (exists $BLESSEDMEMBERS{$field}) { + &$member_func($self,tied(%{$newval})); + } else { + &$member_func($self,$newval); + } +} +</pre></div> + +<p> +Each structure or class is mapped into a Perl package of the same +name. The C++ constructors and destructors are mapped into +constructors and destructors for the package and are always named +"new" and "DESTROY". The constructor always returns a tied hash +table. This hash table is used to access the member variables of a +structure in addition to being able to invoke member functions. The +<tt>%OWNER</tt> and <tt>%BLESSEDMEMBERS</tt> hash tables are used +internally and described shortly. +</p> + +<p> +To use our new proxy class we can simply do the following: +</p> + +<div class="targetlang"><pre> +# Perl code using Vector class +$v = new Vector(2,3,4); +$w = Vector->new(-1,-2,-3); + +# Assignment of a single member +$v->{x} = 7.5; + +# Assignment of all members +%$v = ( x=>3, + y=>9, + z=>-2); + +# Reading members +$x = $v->{x}; + +# Destruction +$v->DESTROY(); + +</pre></div> + +<H3><a name="Perl5_nn42"></a>28.9.3 Object Ownership</H3> + + +<p> +In order for proxy classes to work properly, it is necessary for Perl +to manage some mechanism of object ownership. Here's the crux of the +problem---suppose you had a function like this : +</p> + +<div class="code"><pre> +Vector *Vector_get(Vector *v, int index) { + return &v[i]; +} +</pre></div> + +<p> +This function takes a Vector pointer and returns a pointer to another +Vector. Such a function might be used to manage arrays or lists of +vectors (in C). Now contrast this function with the constructor for a +Vector object : +</p> + +<div class="code"><pre> +Vector *new_Vector(double x, double y, double z) { + Vector *v; + v = new Vector(x,y,z); // Call C++ constructor + return v; +} +</pre></div> + +<p> +Both functions return a Vector, but the constructor is returning a +brand-new Vector while the other function is returning a Vector that +was already created (hopefully). In Perl, both vectors will be +indistinguishable---clearly a problem considering that we would +probably like the newly created Vector to be destroyed when we are +done with it. +</p> + +<p> +To manage these problems, each class contains two methods that access +an internal hash table called <tt>%OWNER</tt>. This hash keeps a list +of all of the objects that Perl knows that it has created. This +happens in two cases: (1) when the constructor has been called, and +(2) when a function implicitly creates a new object (as is done when +SWIG needs to return a complex datatype by value). When the +destructor is invoked, the Perl proxy class module checks the +<tt>%OWNER</tt> hash to see if Perl created the object. If so, the +C/C++ destructor is invoked. If not, we simply destroy the Perl +object and leave the underlying C object alone (under the assumption +that someone else must have created it). +</p> + +<p> +This scheme works remarkably well in practice but it isn't foolproof. +In fact, it will fail if you create a new C object in Perl, pass it on +to a C function that remembers the object, and then destroy the +corresponding Perl object (this situation turns out to come up +frequently when constructing objects like linked lists and trees). +When C takes possession of an object, you can change Perl's ownership +by simply deleting the object from the <tt>%OWNER</tt> hash. This is +done using the <tt>DISOWN</tt> method. +</p> + +<div class="targetlang"><pre> +# Perl code to change ownership of an object +$v = new Vector(x,y,z); +$v->DISOWN(); +</pre></div> + +<p> +To acquire ownership of an object, the <tt>ACQUIRE</tt> method can be used. +</p> + +<div class="targetlang"><pre> +# Given Perl ownership of a file +$u = Vector_get($v); +$u->ACQUIRE(); + +</pre></div> + +<p> +As always, a little care is in order. SWIG does not provide reference +counting, garbage collection, or advanced features one might find in +sophisticated languages. +</p> + +<H3><a name="Perl5_nn43"></a>28.9.4 Nested Objects</H3> + + +<p> +Suppose that we have a new object that looks like this : +</p> + +<div class="code"><pre> +struct Particle { + Vector r; + Vector v; + Vector f; + int type; +} + +</pre></div> + +<p> +In this case, the members of the structure are complex objects that +have already been encapsulated in a Perl proxy class. To handle +these correctly, we use the <tt>%BLESSEDMEMBERS</tt> hash which would +look like this (along with some supporting code) : +</p> + +<div class="targetlang"><pre> +package Particle; +... +%BLESSEDMEMBERS = ( + r => `Vector', + v => `Vector', + f => `Vector', +); + +</pre></div> + +<p> +When fetching members from the structure, <tt>%BLESSEDMEMBERS</tt> is +checked. If the requested field is present, we create a tied-hash +table and return it. If not, we just return the corresponding member +unmodified. +</p> + +<p> +This implementation allows us to operate on nested structures as follows : +</p> + +<div class="targetlang"><pre> +# Perl access of nested structure +$p = new Particle(); +$p->{f}->{x} = 0.0; +%${$p->{v}} = ( x=>0, y=>0, z=>0); +</pre></div> + +<H3><a name="Perl5_nn44"></a>28.9.5 Proxy Functions</H3> + + +<p> +When functions take arguments involving a complex object, it is +sometimes necessary to write a proxy function. For example : +</p> + +<div class="code"><pre> +double dot_product(Vector *v1, Vector *v2); +</pre></div> + +<p> +Since Vector is an object already wrapped into a proxy class, we need +to modify this function to accept arguments that are given in the form +of tied hash tables. This is done by creating a Perl function like +this : +</p> + +<div class="targetlang"><pre> +sub dot_product { + my @args = @_; + $args[0] = tied(%{$args[0]}); # Get the real pointer values + $args[1] = tied(%{$args[1]}); + my $result = vectorc::dot_product(@args); + return $result; +} +</pre></div> + +<p> +This function replaces the original function, but operates in an +identical manner. +</p> + +<H3><a name="Perl5_nn45"></a>28.9.6 Inheritance</H3> + + +<p> +Simple C++ inheritance is handled using the Perl <tt>@ISA</tt> array +in each class package. For example, if you have the following +interface file : +</p> + +<div class="code"><pre> +// shapes.i +// SWIG interface file for shapes class +%module shapes +%{ +#include "shapes.h" +%} + +class Shape { +public: + virtual double area() = 0; + virtual double perimeter() = 0; + void set_location(double x, double y); +}; +class Circle : public Shape { +public: + Circle(double radius); + ~Circle(); + double area(); + double perimeter(); +}; +class Square : public Shape { +public: + Square(double size); + ~Square(); + double area(); + double perimeter(); +} + +</pre></div> + +<p> +The resulting, Perl wrapper class will create the following code : +</p> + +<div class="targetlang"><pre> +Package Shape; +@ISA = (shapes); +... +Package Circle; +@ISA = (shapes Shape); +... +Package Square; +@ISA = (shapes Shape); + +</pre></div> + +<p> +The <tt>@ISA</tt> array determines where to look for methods of a +particular class. In this case, both the <tt>Circle</tt> and +<tt>Square</tt> classes inherit functions from <tt>Shape</tt> so we'll +want to look in the <tt>Shape</tt> base class for them. All classes +also inherit from the top-level module <tt>shapes</tt>. This is +because certain common operations needed to implement proxy classes +are implemented only once and reused in the wrapper code for various +classes and structures. +</p> + +<p> +Since SWIG proxy classes are implemented in Perl, it is easy to +subclass from any SWIG generated class. To do this, simply put the +name of a SWIG class in the <tt>@ISA</tt> array for your new +class. However, be forewarned that this is not a trivial problem. In +particular, inheritance of data members is extremely tricky (and I'm +not even sure if it really works). +</p> + +<H3><a name="Perl5_nn46"></a>28.9.7 Modifying the proxy methods</H3> + + +<p> +It is possible to override the SWIG generated proxy/shadow methods, using <tt>%feature("shadow")</tt>. +It works like all the other <a href="Customization.html#features">%feature directives</a>. +Here is a simple example showing how to add some Perl debug code to the constructor: +</p> + +<div class="targetlang"><pre> +/* Let's make the constructor of the class Square more verbose */ +%feature("shadow") Square(double w) +%{ + sub new { + my $pkg = shift; + my $self = examplec::new_Square(@_); + print STDERR "Constructed an @{[ref($self)]}\n"; + bless $self, $pkg if defined($self); + } +%} + +class Square { +public: + Square(double w); + ... +}; +</pre></div> + +<H2><a name="Perl5_nn47"></a>28.10 Adding additional Perl code</H2> + + +<p> +If writing support code in C isn't enough, it is also possible to write code in +Perl. This code gets inserted in to the <tt>.pm</tt> file created by SWIG. One +use of Perl code might be to supply a high-level interface to certain functions. +For example: +</p> + +<div class="code"> +<pre> +void set_transform(Image *im, double x[4][4]); + +... +/* Rewrite the high level interface to set_transform */ +%perlcode %{ +sub set_transform +{ + my ($im, $x) = @_; + my $a = new_mat44(); + for (my $i = 0; $i < 4, $i++) + { + for (my $j = 0; $j < 4, $j++) + { + mat44_set($a, $i, $j, $x->[i][j]) + } + } + example.set_transform($im, $a); + free_mat44($a); +} +%} +</pre> +</div> + +<p> +In this example, <tt>set_transform()</tt> provides a high-level Perl interface built on top of +low-level helper functions. For example, this code now seems to work: +</p> + +<div class="targetlang"> +<pre> +my $a = + [[1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1]]; +set_transform($im, $a); +</pre> +</div> + + + +</body> +</html> |
