blob: 93f713f108d1f8019516ad0ac74216a7e9d20672 [file] [log] [blame]
<!-- Published by Quadralay WebWorks HTML Lite 1.5.1 -->
<!-- And munged by Dave's special Python script -->
<html>
<head>
<title>Multiple Files and the SWIG Library</title>
</head>
<body bgcolor="#ffffff">
<a name="n0"></a><h1>4 Multiple files and the SWIG library</h1><p><ul>
<li> <a href="#n1">The %include directive</a>
<li> <a href="#n2">The %extern directive</a>
<li> <a href="#n3">The %import directive</a>
<li> <a href="#n4">Including files on the command line</a>
<li> <a href="#n5">The SWIG library</a>
<li> <a href="#n6">Library example</a>
<li> <a href="#n7">Creating Library Files</a>
<li> <a href="#n8">Working with library files</a>
<li> <a href="#n9">Static initialization of multiple modules</a>
<li> <a href="#n10">More about the SWIG library</a>
</ul>
For increased modularity and convenience, it is usually useful to break an interface specification up into multiple files or modules. SWIG provides a number of features for doing just this.<p>
<a name="n1"></a><h2> The %include directive</h2>
The <tt>%include</tt> directive inserts code from another file into the current interface file. It is primarily used to build a package from a collection of smaller modules. For example :<p>
<p>
<blockquote><pre>// File : interface.i
%module package
%include equations.i
%include graphics.i
%include fileio.i
%include data.i
%include network.c
%include "../Include/user.h"
</pre></blockquote>
<p>
When used in this manner, SWIG will create a single wrapper file containing all of the included functions. <p>
<p>
The <tt>%include</tt> directive can process SWIG interface files, C header files, and C source files (provided they are sufficiently clean). When processing a C source file, SWIG will automatically declare all functions it finds as "extern". Thus, use of a header file may not be required in this case.<p>
<a name="n2"></a><h2> The %extern directive</h2>
The <tt>%extern</tt> directive is like <tt>%include</tt> except that it only scans a file for type and class information. It does not actually wrap anything found in the input file. This directive is primarily used for handling class hierarchies and multiple modules. For example :<p>
<p>
<blockquote><pre>%module derived
%extern baseclass.h // Grab definition of a base class
// Now wrap a derived class
class Derived : public BaseClass {
public:
...
};
</pre></blockquote>
This interface file would grab the member functions and data from a baseclass, but only use them in the specification of a derived class. <tt>%extern</tt> processing of files is also useful for picking up common typedefs and definitions in a large package.<p>
<a name="n3"></a><h2> The %import directive</h2>
The <tt>%extern</tt> directive is used to gather declarations from files that you don't want to wrap into an interface. Unfornunately, the exact role of these files is not always clear. They could just contain definitions, or they might correspond to an entrirely different SWIG module. The <tt>%import</tt> directive is a stronger version of <tt>%extern</tt> that tells SWIG that all of the declarations in the file are indeed, in an entirely different module. This information may affect the code generated by various language modules since they will have a better idea of where things are defined and how they are to be used.<p>
<a name="n4"></a><h2> Including files on the command line</h2>
Much like the C or C++ compiler, SWIG can also include library files on the command line using the <tt>-l</tt> option as shown<p>
<p>
<blockquote><pre>
# Include a library file at compile time
% swig -tcl -lwish.i interface.i
</pre></blockquote>
This approach turns out to be particularly useful for debugging and building extensions to different kinds of languages. When libraries are specified in this manner, they are included after all of the declarations in <tt>interface.i</tt> have been wrapped. Thus, this does not work if you are trying to include common declarations, typemaps, and other files.<p>
<a name="n5"></a><h2> The SWIG library </h2>
SWIG comes with a library of functions that can be used to build up more complex interfaces. As you build up a collection of modules, you may also find yourself with a large number of interface files. While the <tt>%include</tt> directive can be used to insert files, it also searches the files installed in the SWIG library (think of this as the SWIG equivalent of the C library). When you use <tt>%include</tt>, SWIG will search for the file in the following order :<p>
<p>
<ul>
<li>The current directory
<li>Directories specified with the -I option
<li>.<tt>/swig_lib</tt>
<li><tt>/usr/local/lib/swig_lib</tt> (or wherever you installed SWIG)
</ul>
<p>
Within each directory, you can also create subdirectories for each target language. If found, SWIG will search these directories first, allowing the creation of language-specific implementations of a particular library file.<p>
<p>
You can override the location of the SWIG library by setting the <tt>SWIG_LIB</tt> environment variable.<p>
<a name="n6"></a><h2> Library example</h2>
The SWIG library is really a repository of "useful modules" that can be used to build better interfaces. To use a library file, you can simply use the <tt>%include </tt>directive with the name of a library file. For example :<p>
<p>
<blockquote><pre>%module example
%include pointer.i // Grab the SWIG pointer library
// a+b --&gt; c
extern double add(double a, double b, double *c);
</pre></blockquote>
In this example, we are including the SWIG pointer library that adds functions for manipulating C pointers. These added functions become part of your module that can be used as needed. For example, we can write a Tcl script like this that involves both the <tt>add()</tt> function and two functions from the <tt>pointer.i</tt> library :<p>
<p>
<blockquote><pre>set c [ptrcreate double 0] ;# Create a double * for holding the result
add 4 3.5 $c ;# Call our C function
puts [ptrvalue $c] ;# Print out the result
</pre></blockquote>
<a name="n7"></a><h2> Creating Library Files</h2>
It is easy to create your own library files. To illustrate the process, we consider two different library files--one to build a new <tt>tclsh</tt> program, and one to add a few memory management functions.<p>
<a name="n11"></a><h3> tclsh.i</h3>
To build a new <tt>tclsh</tt> application, you need to supply a <tt>Tcl_AppInit()</tt> function. This can be done using the following SWIG interface file (simplified somewhat for clarity) :<p>
<blockquote><pre>
// File : tclsh.i
%{
#if TCL_MAJOR_VERSION == 7 &amp;&amp; TCL_MINOR_VERSION &gt;= 4
int main(int argc, char **argv) {
Tcl_Main(argc, argv, Tcl_AppInit);
return(0);
}
#else
extern int main();
#endif
int Tcl_AppInit(Tcl_Interp *interp){
int SWIG_init(Tcl_Interp *);
if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
/* Now initialize our functions */
if (SWIG_init(interp) == TCL_ERROR)
return TCL_ERROR;
return TCL_OK;
}
%}
</pre></blockquote>
In this case, the entire file consists of a single code block. This code will be inserted directly into the resulting wrapper file, providing us with the needed <tt>Tcl_AppInit()</tt> function.<p>
<a name="n12"></a><h3> malloc.i</h3>
Now suppose we wanted to write a file <tt>malloc.i</tt> that added a few memory management functions. We could do the following :<p>
<p>
<blockquote><pre>// File : malloc.i
%{
#include &lt;malloc.h&gt;
%}
%typedef unsigned int size_t
void *malloc(size_t nbytes);
void *realloc(void *ptr, size_t nbytes);
void free(void *);
</pre></blockquote>
<p>
In this case, we have a general purpose library that could be used whenever we needed access to the <tt>malloc()</tt> functions. Since this interface file is language independent, we can use it anywhere.<p>
<a name="n13"></a><h3> Placing the files in the library</h3>
While both of our examples are SWIG interface files, they are quite different in functionality since <tt>tclsh.i</tt> would only work with Tcl while <tt>malloc.i</tt> would work with any of the target languages. Thus, we should put these files into the SWIG library as follows :<p>
<blockquote><pre><tt>
./swig_lib/malloc.i
./swig_lib/tcl/tclsh.i
</tt></pre></blockquote>
<p>
When used in other interface files, this allows us to use <tt>malloc.i</tt> with any target language while <tt>tclsh.i</tt> will only be accessible if creating for wrappers for Tcl (ie. when creating a Perl5 module, SWIG will not look in the <tt>tcl</tt> subdirectory.<p>
<p>
It should be noted that language specific libraries can mask general libraries. For example, if you wanted to make a Perl specific modification to <tt>malloc.i</tt>, you could make a special version and call it <tt>./swig_lib/perl5/malloc.i</tt>. When using Perl, you'd get this version, while all other target languages would use the general purpose version.<p>
<a name="n8"></a><h2> Working with library files</h2>
There are a variety of additional methods for working with files in the SWIG library described next.<p>
<a name="n14"></a><h3> Wrapping a library file</h3>
If you would like to wrap a file in the SWIG library, simply give SWIG the name of the appropriate library file on the command line. For example :<p>
<p>
<blockquote><pre>unix &gt; swig -python pointer.i
</pre></blockquote>
If the file <tt>pointer.i</tt> is not in the current directory, SWIG will look it up in the library, generate wrapper code, and place the output in the current directory. This technique can be used to quickly make a module out of a library file regardless of where you are working.<p>
<a name="n15"></a><h3> Checking out library files</h3>
At times, it is useful to check a file out of the library and copy it into the working directory. This allows you to modify the file or to simply retrieve useful files. To check a file out of the library, run SWIG as follows :<p>
<p>
<blockquote><pre>unix &gt; swig -co -python array.i
array.i checked out from the SWIG library
unix &gt;
</pre></blockquote>
The library file will be placed in the current directory unless a file with the same name already exists (in which case nothing is done). <p>
<p>
The SWIG library is not restricted to interface files. Suppose you had a cool Perl script that you liked to use alot. You could place this in the SWIG library. Now whenever you wanted to use it, you could retrieve it by issuing :<p>
<p>
<blockquote><pre>unix &gt; swig -perl5 -co myscript.pl
myscript.pl checked out from the SWIG library
</pre></blockquote>
Support files can also be checked out within an interface file using the <tt>%checkout</tt> directive.<p>
<p>
<blockquote><pre>%checkout myscript.pl
</pre></blockquote>
This will attempt to copy the file <tt>myscript.pl</tt> to the current directory when SWIG is run. If the file already exists, nothing is done.<p>
<a name="n16"></a><h3> The world's fastest way to write a Makefile</h3>
Since the SWIG library is not restricted to SWIG interface files, it can be used to hold other kinds of useful files. For example, if you need a quick Makefile for building Tcl extensions, type the following:<p>
<blockquote><pre>
unix&gt; swig -tcl -co Makefile
Makefile checked out from the SWIG library
</pre></blockquote>
During installation, SWIG creates a collection of preconfigured Makefiles for various scripting languages. If you need to make a new module, just check out one of these Makefiles, make a few changes, and you should be ready to compile and extension for your system.<p>
<a name="n17"></a><h3> Checking in library files</h3>
It is also possible to check files into the SWIG library. If you've made an interesting interface that you would like to keep around, simply type :<p>
<p>
<blockquote><pre>unix &gt; swig -ci -python cool.i
</pre></blockquote>
and the file `<tt>cool.i</tt>' will be placed in the Python section of the library. If your interface file is general purpose, you can install it into the general library as follows :<p>
<p>
<blockquote><pre>unix &gt; swig -ci ../cool.i
</pre></blockquote>
When files are checked in, they are placed into the directory defined by the <tt>SWIG_LIB</tt> variable that was used during SWIG compilation or the <tt>SWIG_LIB</tt> environment variable (if set). If you don't know what the value of this variable is, type the following to display its location.<p>
<p>
<blockquote><pre>unix &gt; swig -swiglib
/usr/local/lib/swig_lib
unix &gt;
</pre></blockquote>
<p>
In order to check files into the library, you must have write permission on the library directory. For this reason, one of the primary uses for the <tt>-ci</tt> option is to provide a simple mechanism for installing SWIG extensions. If these extensions need to install library files, that can be done by simply running SWIG.<p>
<a name="n9"></a><h2> Static initialization of multiple modules</h2>
When using static linking, some language modules allow multiple modules to be initialized as follows :<p>
<p>
<blockquote><pre>%module package, equations, graphics, fileio, data, network, user
... More declarations ...
</pre></blockquote>
The module list can contain SWIG generated modules or third-party applications. Refer to the appropriate language chapter for a detailed description of this feature.<p>
<a name="n10"></a><h2> More about the SWIG library</h2>
Full documentation about the SWIG library is included in the SWIG source distribution. In fact, the documentation is automatically generated by SWIG, which leads us to the next section...<p>
<p>
<p><hr>
<address>SWIG 1.1 - Last Modified : Mon Aug 4 10:46:54 1997</address>
</body>
</html>