mirror of https://github.com/swig/swig
470 lines
14 KiB
HTML
470 lines
14 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>Scripting Languages</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<H1><a name="Scripting"></a>4 Scripting Languages</H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#Scripting_nn2">The two language view of the world</a>
|
|
<li><a href="#Scripting_nn3">How does a scripting language talk to C?</a>
|
|
<ul>
|
|
<li><a href="#Scripting_nn4">Wrapper functions</a>
|
|
<li><a href="#Scripting_nn5">Variable linking</a>
|
|
<li><a href="#Scripting_nn6">Constants</a>
|
|
<li><a href="#Scripting_nn7">Structures and classes</a>
|
|
<li><a href="#Scripting_nn8">Proxy classes</a>
|
|
</ul>
|
|
<li><a href="#Scripting_nn9">Building scripting language extensions</a>
|
|
<ul>
|
|
<li><a href="#Scripting_nn10">Shared libraries and dynamic loading</a>
|
|
<li><a href="#Scripting_nn11">Linking with shared libraries</a>
|
|
<li><a href="#Scripting_nn12">Static linking</a>
|
|
</ul>
|
|
</ul>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<p>
|
|
This chapter provides a brief overview of scripting language extension
|
|
programming and the mechanisms by which scripting language interpreters
|
|
access C and C++ code.
|
|
</p>
|
|
|
|
<H2><a name="Scripting_nn2"></a>4.1 The two language view of the world</H2>
|
|
|
|
|
|
<p>
|
|
When a scripting language is used to control a C program, the
|
|
resulting system tends to look as follows:
|
|
</p>
|
|
|
|
<center><img src="ch2.1.png" alt="Scripting language input - C/C++ functions output"></center>
|
|
|
|
<p>
|
|
In this programming model, the scripting language interpreter is used
|
|
for high level control whereas the underlying functionality of the
|
|
C/C++ program is accessed through special scripting language
|
|
"commands." If you have ever tried to write your own simple command
|
|
interpreter, you might view the scripting language approach
|
|
to be a highly advanced implementation of that. Likewise,
|
|
If you have ever used a package such as MATLAB or IDL, it is a
|
|
very similar model--the interpreter executes user commands and
|
|
scripts. However, most of the underlying functionality is written in
|
|
a low-level language like C or Fortran.
|
|
</p>
|
|
|
|
<p>
|
|
The two-language model of computing is extremely powerful because it
|
|
exploits the strengths of each language. C/C++ can be used for maximal
|
|
performance and complicated systems programming tasks. Scripting
|
|
languages can be used for rapid prototyping, interactive debugging,
|
|
scripting, and access to high-level data structures such associative
|
|
arrays. </p>
|
|
|
|
<H2><a name="Scripting_nn3"></a>4.2 How does a scripting language talk to C?</H2>
|
|
|
|
|
|
<p>
|
|
Scripting languages are built around a parser that knows how
|
|
to execute commands and scripts. Within this parser, there is a
|
|
mechanism for executing commands and accessing variables.
|
|
Normally, this is used to implement the builtin features
|
|
of the language. However, by extending the interpreter, it is usually
|
|
possible to add new commands and variables. To do this,
|
|
most languages define a special API for adding new commands.
|
|
Furthermore, a special foreign function interface defines how these
|
|
new commands are supposed to hook into the interpreter.
|
|
</p>
|
|
|
|
<p>
|
|
Typically, when you add a new command to a scripting interpreter
|
|
you need to do two things; first you need to write a special
|
|
"wrapper" function that serves as the glue between the interpreter
|
|
and the underlying C function. Then you need to give the interpreter
|
|
information about the wrapper by providing details about the name of the
|
|
function, arguments, and so forth. The next few sections illustrate
|
|
the process.
|
|
</p>
|
|
|
|
<H3><a name="Scripting_nn4"></a>4.2.1 Wrapper functions</H3>
|
|
|
|
|
|
<p>
|
|
Suppose you have an ordinary C function like this :</p>
|
|
|
|
<div class="code"><pre>
|
|
int fact(int n) {
|
|
if (n <= 1) return 1;
|
|
else return n*fact(n-1);
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
In order to access this function from a scripting language, it is
|
|
necessary to write a special "wrapper" function that serves as the
|
|
glue between the scripting language and the underlying C function. A
|
|
wrapper function must do three things :</p>
|
|
|
|
<ul>
|
|
<li>Gather function arguments and make sure they are valid.
|
|
<li>Call the C function.
|
|
<li>Convert the return value into a form recognized by the scripting language.
|
|
</ul>
|
|
|
|
<p>
|
|
As an example, the Tcl wrapper function for the <tt>fact()</tt>
|
|
function above example might look like the following : </p>
|
|
|
|
<div class="code"><pre>
|
|
int wrap_fact(ClientData clientData, Tcl_Interp *interp,
|
|
int argc, char *argv[]) {
|
|
int result;
|
|
int arg0;
|
|
if (argc != 2) {
|
|
interp->result = "wrong # args";
|
|
return TCL_ERROR;
|
|
}
|
|
arg0 = atoi(argv[1]);
|
|
result = fact(arg0);
|
|
sprintf(interp->result,"%d", result);
|
|
return TCL_OK;
|
|
}
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
Once you have created a wrapper function, the final step is to tell the
|
|
scripting language about the new function. This is usually done in an
|
|
initialization function called by the language when the module is
|
|
loaded. For example, adding the above function to the Tcl interpreter
|
|
requires code like the following :</p>
|
|
|
|
<div class="code"><pre>
|
|
int Wrap_Init(Tcl_Interp *interp) {
|
|
Tcl_CreateCommand(interp, "fact", wrap_fact, (ClientData) NULL,
|
|
(Tcl_CmdDeleteProc *) NULL);
|
|
return TCL_OK;
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
When executed, Tcl will now have a new command called "<tt>fact</tt>"
|
|
that you can use like any other Tcl command.</p>
|
|
|
|
<p>
|
|
Although the process of adding a new function to Tcl has been
|
|
illustrated, the procedure is almost identical for Perl and
|
|
Python. Both require special wrappers to be written and both need
|
|
additional initialization code. Only the specific details are
|
|
different.</p>
|
|
|
|
<H3><a name="Scripting_nn5"></a>4.2.2 Variable linking</H3>
|
|
|
|
|
|
<p>
|
|
Variable linking refers to the problem of mapping a
|
|
C/C++ global variable to a variable in the scripting
|
|
language interpreter. For example, suppose you had the following
|
|
variable:</p>
|
|
|
|
<div class="code"><pre>
|
|
double Foo = 3.5;
|
|
</pre></div>
|
|
|
|
<p>
|
|
It might be nice to access it from a script as follows (shown for Perl):</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
$a = $Foo * 2.3; # Evaluation
|
|
$Foo = $a + 2.0; # Assignment
|
|
</pre></div>
|
|
|
|
<p>
|
|
To provide such access, variables are commonly manipulated using a
|
|
pair of get/set functions. For example, whenever the value of a
|
|
variable is read, a "get" function is invoked. Similarly, whenever
|
|
the value of a variable is changed, a "set" function is called.
|
|
</p>
|
|
|
|
<p>
|
|
In many languages, calls to the get/set functions can be attached to
|
|
evaluation and assignment operators. Therefore, evaluating a variable
|
|
such as <tt>$Foo</tt> might implicitly call the get function. Similarly,
|
|
typing <tt>$Foo = 4</tt> would call the underlying set function to change
|
|
the value.
|
|
</p>
|
|
|
|
<H3><a name="Scripting_nn6"></a>4.2.3 Constants</H3>
|
|
|
|
|
|
<p>
|
|
In many cases, a C program or library may define a large collection of
|
|
constants. For example:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
#define RED 0xff0000
|
|
#define BLUE 0x0000ff
|
|
#define GREEN 0x00ff00
|
|
</pre></div>
|
|
<p>
|
|
To make constants available, their values can be stored in scripting
|
|
language variables such as <tt>$RED</tt>, <tt>$BLUE</tt>, and
|
|
<tt>$GREEN</tt>. Virtually all scripting languages provide C
|
|
functions for creating variables so installing constants is usually
|
|
a trivial exercise.
|
|
</p>
|
|
|
|
<H3><a name="Scripting_nn7"></a>4.2.4 Structures and classes</H3>
|
|
|
|
|
|
<p>
|
|
Although scripting languages have no trouble accessing simple
|
|
functions and variables, accessing C/C++ structures and classes
|
|
present a different problem. This is because the implementation
|
|
of structures is largely related to the problem of
|
|
data representation and layout. Furthermore, certain language features
|
|
are difficult to map to an interpreter. For instance, what
|
|
does C++ inheritance mean in a Perl interface?
|
|
</p>
|
|
|
|
<p>
|
|
The most straightforward technique for handling structures is to
|
|
implement a collection of accessor functions that hide the underlying
|
|
representation of a structure. For example,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
struct Vector {
|
|
Vector();
|
|
~Vector();
|
|
double x,y,z;
|
|
};
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
can be transformed into the following set of functions :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
Vector *new_Vector();
|
|
void delete_Vector(Vector *v);
|
|
double Vector_x_get(Vector *v);
|
|
double Vector_y_get(Vector *v);
|
|
double Vector_z_get(Vector *v);
|
|
void Vector_x_set(Vector *v, double x);
|
|
void Vector_y_set(Vector *v, double y);
|
|
void Vector_z_set(Vector *v, double z);
|
|
|
|
</pre></div>
|
|
<p>
|
|
Now, from an interpreter these function might be used as follows:
|
|
</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
% set v [new_Vector]
|
|
% Vector_x_set $v 3.5
|
|
% Vector_y_get $v
|
|
% delete_Vector $v
|
|
% ...
|
|
</pre></div>
|
|
|
|
<p>
|
|
Since accessor functions provide a mechanism for accessing the
|
|
internals of an object, the interpreter does not need to know anything
|
|
about the actual representation of a <tt>Vector</tt>.
|
|
</p>
|
|
|
|
<H3><a name="Scripting_nn8"></a>4.2.5 Proxy classes</H3>
|
|
|
|
|
|
<p>
|
|
In certain cases, it is possible to use the low-level accessor functions
|
|
to create a proxy class, also known as a shadow class.
|
|
A proxy class is a special kind of object that gets created
|
|
in a scripting language to access a C/C++ class (or struct) in a way
|
|
that looks like the original structure (that is, it proxies the real
|
|
C++ class). For example, if you
|
|
have the following C++ definition :</p>
|
|
|
|
<div class="code"><pre>
|
|
class Vector {
|
|
public:
|
|
Vector();
|
|
~Vector();
|
|
double x,y,z;
|
|
};
|
|
</pre></div>
|
|
|
|
<p>
|
|
A proxy classing mechanism would allow you to access the structure in
|
|
a more natural manner from the interpreter. For example, in Python, you might want to do this:
|
|
</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
>>> v = Vector()
|
|
>>> v.x = 3
|
|
>>> v.y = 4
|
|
>>> v.z = -13
|
|
>>> ...
|
|
>>> del v
|
|
</pre></div>
|
|
|
|
<p>
|
|
Similarly, in Perl5 you may want the interface to work like this:</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
$v = new Vector;
|
|
$v->{x} = 3;
|
|
$v->{y} = 4;
|
|
$v->{z} = -13;
|
|
|
|
</pre></div>
|
|
<p>
|
|
Finally, in Tcl :
|
|
</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
Vector v
|
|
v configure -x 3 -y 4 -z -13
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
When proxy classes are used, two objects are really at work--one in
|
|
the scripting language, and an underlying C/C++ object. Operations
|
|
affect both objects equally and for all practical purposes, it appears
|
|
as if you are simply manipulating a C/C++ object.
|
|
</p>
|
|
|
|
<H2><a name="Scripting_nn9"></a>4.3 Building scripting language extensions</H2>
|
|
|
|
|
|
<p>
|
|
The final step in using a scripting language with your C/C++
|
|
application is adding your extensions to the scripting language
|
|
itself. There are two primary approaches for doing
|
|
this. The preferred technique is to build a dynamically loadable
|
|
extension in the form of a shared library. Alternatively, you can
|
|
recompile the scripting language interpreter with your extensions
|
|
added to it.
|
|
</p>
|
|
|
|
<H3><a name="Scripting_nn10"></a>4.3.1 Shared libraries and dynamic loading</H3>
|
|
|
|
|
|
<p>
|
|
To create a shared library or DLL, you often need to look at the
|
|
manual pages for your compiler and linker. However, the procedure
|
|
for a few common platforms is shown below:</p>
|
|
|
|
<div class="shell"><pre>
|
|
# Build a shared library for Solaris
|
|
gcc -fpic -c example.c example_wrap.c -I/usr/local/include
|
|
ld -G example.o example_wrap.o -o example.so
|
|
|
|
# Build a shared library for Linux
|
|
gcc -fpic -c example.c example_wrap.c -I/usr/local/include
|
|
gcc -shared example.o example_wrap.o -o example.so
|
|
</pre></div>
|
|
|
|
<p>
|
|
To use your shared library, you simply use the corresponding command
|
|
in the scripting language (load, import, use, etc...). This will
|
|
import your module and allow you to start using it. For example:
|
|
</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
% load ./example.so
|
|
% fact 4
|
|
24
|
|
%
|
|
</pre></div>
|
|
|
|
<p>
|
|
When working with C++ codes, the process of building shared libraries
|
|
may be more complicated--primarily due to the fact that C++ modules may need
|
|
additional code in order to operate correctly. On many machines, you
|
|
can build a shared C++ module by following the above procedures, but
|
|
changing the link line to the following :</p>
|
|
|
|
<div class="shell"><pre>
|
|
c++ -shared example.o example_wrap.o -o example.so
|
|
</pre></div>
|
|
|
|
<H3><a name="Scripting_nn11"></a>4.3.2 Linking with shared libraries</H3>
|
|
|
|
|
|
<p>
|
|
When building extensions as shared libraries, it is not uncommon for
|
|
your extension to rely upon other shared libraries on your machine. In
|
|
order for the extension to work, it needs to be able to find all of
|
|
these libraries at run-time. Otherwise, you may get an error such as
|
|
the following :</p>
|
|
|
|
<div class="targetlang"><pre>
|
|
>>> import graph
|
|
Traceback (innermost last):
|
|
File "<stdin>", line 1, in ?
|
|
File "/home/sci/data1/beazley/graph/graph.py", line 2, in ?
|
|
import graphc
|
|
ImportError: 1101:/home/sci/data1/beazley/bin/python: rld: Fatal Error: cannot
|
|
successfully map soname 'libgraph.so' under any of the filenames /usr/lib/libgraph.so:/
|
|
lib/libgraph.so:/lib/cmplrs/cc/libgraph.so:/usr/lib/cmplrs/cc/libgraph.so:
|
|
>>>
|
|
</pre></div>
|
|
<p>
|
|
|
|
What this error means is that the extension module created by SWIG
|
|
depends upon a shared library called "<tt>libgraph.so</tt>" that the
|
|
system was unable to locate. To fix this problem, there are a few
|
|
approaches you can take.</p>
|
|
|
|
<ul>
|
|
<li>Link your extension and explicitly tell the linker where the
|
|
required libraries are located. Often times, this can be done with a
|
|
special linker flag such as <tt>-R</tt>, <tt>-rpath</tt>, etc. This
|
|
is not implemented in a standard manner so read the man pages for your
|
|
linker to find out more about how to set the search path for shared
|
|
libraries.
|
|
|
|
<li>Put shared libraries in the same directory as the executable. This
|
|
technique is sometimes required for correct operation on non-Unix
|
|
platforms.
|
|
|
|
<li>Set the UNIX environment variable <tt>LD_LIBRARY_PATH</tt> to the
|
|
directory where shared libraries are located before running Python.
|
|
Although this is an easy solution, it is not recommended. Consider setting
|
|
the path using linker options instead.
|
|
|
|
</ul>
|
|
|
|
<H3><a name="Scripting_nn12"></a>4.3.3 Static linking</H3>
|
|
|
|
|
|
<p>
|
|
With static linking, you rebuild the scripting language interpreter
|
|
with extensions. The process usually involves compiling a short main
|
|
program that adds your customized commands to the language and starts
|
|
the interpreter. You then link your program with a library to produce
|
|
a new scripting language executable.
|
|
</p>
|
|
|
|
<p>
|
|
Although static linking is supported on all platforms, this is not
|
|
the preferred technique for building scripting language
|
|
extensions. In fact, there are very few practical reasons for doing this--consider
|
|
using shared libraries instead.
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|