Thousands of changes to correct incorrect HTML. HTML is now valid (transitional 4.01).
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6074 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
7cb896a5f4
commit
aa4d1d907d
31 changed files with 6754 additions and 4801 deletions
|
|
@ -5,23 +5,23 @@
|
|||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
<a name="n1"></a><H1>3 Scripting Languages</H1>
|
||||
<H1><a name="Scripting"></a>4 Scripting Languages</H1>
|
||||
<!-- INDEX -->
|
||||
<ul>
|
||||
<li><a href="#n2">The two language view of the world</a>
|
||||
<li><a href="#n3">How does a scripting language talk to C?</a>
|
||||
<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="#n4">Wrapper functions</a>
|
||||
<li><a href="#n5">Variable linking</a>
|
||||
<li><a href="#n6">Constants</a>
|
||||
<li><a href="#n7">Structures and classes</a>
|
||||
<li><a href="#n8">Shadow classes</a>
|
||||
<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">Shadow classes</a>
|
||||
</ul>
|
||||
<li><a href="#n9">Building scripting language extensions</a>
|
||||
<li><a href="#Scripting_nn9">Building scripting language extensions</a>
|
||||
<ul>
|
||||
<li><a href="#n10">Shared libraries and dynamic loading</a>
|
||||
<li><a href="#n11">Linking with shared libraries</a>
|
||||
<li><a href="#n12">Static linking</a>
|
||||
<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>
|
||||
<!-- INDEX -->
|
||||
|
|
@ -32,16 +32,17 @@ This chapter provides a brief overview of scripting language extension
|
|||
programming and the mechanisms by which scripting language interpreters
|
||||
access C and C++ code.
|
||||
|
||||
<a name="n2"></a><H2>3.1 The two language view of the world</H2>
|
||||
<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>
|
||||
|
||||
<p><center><img src="ch2.1.png"></center><p>
|
||||
<p>
|
||||
<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
|
||||
|
|
@ -52,6 +53,7 @@ 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
|
||||
|
|
@ -59,9 +61,9 @@ 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>
|
||||
arrays. </p>
|
||||
|
||||
<a name="n3"></a><H2>3.2 How does a scripting language talk to C?</H2>
|
||||
<H2><a name="Scripting_nn3"></a>4.2 How does a scripting language talk to C?</H2>
|
||||
|
||||
|
||||
Scripting languages are built around a parser that knows how
|
||||
|
|
@ -82,14 +84,16 @@ 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>
|
||||
|
||||
<a name="n4"></a><H3>3.2.1 Wrapper functions</H3>
|
||||
<H3><a name="Scripting_nn4"></a>4.2.1 Wrapper functions</H3>
|
||||
|
||||
|
||||
Suppose you have an ordinary C function like this :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>int fact(int n) {
|
||||
Suppose you have an ordinary C function like this :</p>
|
||||
|
||||
<blockquote><pre>
|
||||
int fact(int n) {
|
||||
if (n <= 1) return 1;
|
||||
else return n*fact(n-1);
|
||||
}
|
||||
|
|
@ -99,18 +103,17 @@ Suppose you have an ordinary C function like this :<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>
|
||||
wrapper function must do three things :</p>
|
||||
|
||||
<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>
|
||||
|
||||
<p>
|
||||
As an example, the Tcl wrapper function for the <tt>fact()</tt>
|
||||
function above example might look like the following : <p>
|
||||
function above example might look like the following : </p>
|
||||
|
||||
<blockquote><pre>
|
||||
int wrap_fact(ClientData clientData, Tcl_Interp *interp,
|
||||
|
|
@ -129,14 +132,15 @@ int wrap_fact(ClientData clientData, Tcl_Interp *interp,
|
|||
|
||||
</pre></blockquote>
|
||||
|
||||
<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>
|
||||
requires code like the following :</p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>int Wrap_Init(Tcl_Interp *interp) {
|
||||
<blockquote><pre>
|
||||
int Wrap_Init(Tcl_Interp *interp) {
|
||||
Tcl_CreateCommand(interp, "fact", wrap_fact, (ClientData) NULL,
|
||||
(Tcl_CmdDeleteProc *) NULL);
|
||||
return TCL_OK;
|
||||
|
|
@ -145,41 +149,42 @@ requires code like the following :<p>
|
|||
|
||||
<p>
|
||||
When executed, Tcl will now have a new command called "<tt>fact</tt>"
|
||||
that you can use like any other Tcl command.<p>
|
||||
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>
|
||||
different.</p>
|
||||
|
||||
<a name="n5"></a><H3>3.2.2 Variable linking</H3>
|
||||
<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 interpeter. For example, suppose you had the following
|
||||
variable:<p>
|
||||
<p>
|
||||
variable:</p>
|
||||
|
||||
<blockquote><pre>double Foo = 3.5;
|
||||
<blockquote><pre>
|
||||
double Foo = 3.5;
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
It might be nice to access it from a script as follows (shown for Perl):<p>
|
||||
It might be nice to access it from a script as follows (shown for Perl):</p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>$a = $Foo * 2.3; # Evaluation
|
||||
<blockquote><pre>
|
||||
$a = $Foo * 2.3; # Evaluation
|
||||
$Foo = $a + 2.0; # Assignment
|
||||
</pre></blockquote>
|
||||
|
||||
<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
|
||||
|
|
@ -187,14 +192,16 @@ 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>
|
||||
|
||||
<a name="n6"></a><H3>3.2.3 Constants</H3>
|
||||
<H3><a name="Scripting_nn6"></a>4.2.3 Constants</H3>
|
||||
|
||||
|
||||
In many cases, a C program or library may define a large collection of
|
||||
constants. For example:
|
||||
|
||||
<blockquote><pre>#define RED 0xff0000
|
||||
<blockquote><pre>
|
||||
#define RED 0xff0000
|
||||
#define BLUE 0x0000ff
|
||||
#define GREEN 0x00ff00
|
||||
</pre></blockquote>
|
||||
|
|
@ -205,7 +212,7 @@ language variables such as <tt>$RED</tt>, <tt>$BLUE</tt>, and
|
|||
functions for creating variables so installing constants is usually
|
||||
a trivial exercise.
|
||||
|
||||
<a name="n7"></a><H3>3.2.4 Structures and classes</H3>
|
||||
<H3><a name="Scripting_nn7"></a>4.2.4 Structures and classes</H3>
|
||||
|
||||
|
||||
Although scripting languages have no trouble accessing simple
|
||||
|
|
@ -220,19 +227,20 @@ does C++ inheritance mean in a Perl interface?
|
|||
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>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>struct Vector {
|
||||
<blockquote><pre>
|
||||
struct Vector {
|
||||
Vector();
|
||||
~Vector();
|
||||
double x,y,z;
|
||||
};
|
||||
|
||||
</pre></blockquote>
|
||||
can be transformed into the following set of functions :<p>
|
||||
can be transformed into the following set of functions :
|
||||
|
||||
<p>
|
||||
<blockquote><pre>Vector *new_Vector();
|
||||
<blockquote><pre>
|
||||
Vector *new_Vector();
|
||||
void delete_Vector(Vector *v);
|
||||
double Vector_x_get(Vector *v);
|
||||
double Vector_y_get(Vector *v);
|
||||
|
|
@ -245,29 +253,31 @@ void Vector_z_set(Vector *v, double z);
|
|||
|
||||
Now, from an interpreter these function might be used as follows:
|
||||
|
||||
<p>
|
||||
<blockquote><pre>% set v [new_Vector]
|
||||
<blockquote><pre>
|
||||
% set v [new_Vector]
|
||||
% Vector_x_set $v 3.5
|
||||
% Vector_y_get $v
|
||||
% delete_Vector $v
|
||||
% ...
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
|
||||
<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>
|
||||
|
||||
<a name="n8"></a><H3>3.2.5 Shadow classes</H3>
|
||||
<H3><a name="Scripting_nn8"></a>4.2.5 Shadow classes</H3>
|
||||
|
||||
|
||||
<p>
|
||||
In certain cases, it is possible to use the low-level accessor functions
|
||||
to create something known as a "shadow" class.
|
||||
A "shadow 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 "shadows" the real
|
||||
C++ class). For example, if you
|
||||
have the following C definition :<p>
|
||||
have the following C definition :</p>
|
||||
|
||||
<blockquote><pre>
|
||||
class Vector {
|
||||
|
|
@ -277,13 +287,14 @@ public:
|
|||
double x,y,z;
|
||||
};
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
|
||||
<p>
|
||||
A shadow 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>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>>>> v = Vector()
|
||||
<blockquote><pre>
|
||||
>>> v = Vector()
|
||||
>>> v.x = 3
|
||||
>>> v.y = 4
|
||||
>>> v.z = -13
|
||||
|
|
@ -292,7 +303,7 @@ a more natural manner from the interpreter. For example, in Python, you might wa
|
|||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Similarly, in Perl5 you may want the interface to work like this:<p>
|
||||
Similarly, in Perl5 you may want the interface to work like this:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
$v = new Vector;
|
||||
|
|
@ -302,7 +313,7 @@ $v->{z} = -13;
|
|||
|
||||
</pre></blockquote>
|
||||
|
||||
Finally, in Tcl :<p>
|
||||
Finally, in Tcl :
|
||||
|
||||
<blockquote><pre>
|
||||
Vector v
|
||||
|
|
@ -310,14 +321,17 @@ v configure -x 3 -y 4 -z 13
|
|||
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
When shadow classes are used, two objects are at really 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>
|
||||
|
||||
<a name="n9"></a><H2>3.3 Building scripting language extensions</H2>
|
||||
<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
|
||||
|
|
@ -325,16 +339,18 @@ this. The preferred technique is to build a dynamically loadable
|
|||
extension in the form a shared library. Alternatively, you can
|
||||
recompile the scripting language interpreter with your extensions
|
||||
added to it.
|
||||
</p>
|
||||
|
||||
<a name="n10"></a><H3>3.3.1 Shared libraries and dynamic loading</H3>
|
||||
<H3><a name="Scripting_nn10"></a>4.3.1 Shared libraries and dynamic loading</H3>
|
||||
|
||||
|
||||
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 machines is shown below:<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre># Build a shared library for Solaris
|
||||
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 machines is shown below:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
# Build a shared library for Solaris
|
||||
gcc -c example.c example_wrap.c -I/usr/local/include
|
||||
ld -G example.o example_wrap.o -o example.so
|
||||
|
||||
|
|
@ -348,12 +364,14 @@ ld -shared example.o example_wrap.o -o example.so
|
|||
|
||||
</pre></blockquote>
|
||||
|
||||
<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>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>% load ./example.so
|
||||
<blockquote><pre>
|
||||
% load ./example.so
|
||||
% fact 4
|
||||
24
|
||||
%
|
||||
|
|
@ -364,24 +382,24 @@ 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>
|
||||
changing the link line to the following :</p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>c++ -shared example.o example_wrap.o -o example.so
|
||||
<blockquote><pre>
|
||||
c++ -shared example.o example_wrap.o -o example.so
|
||||
</pre></blockquote>
|
||||
|
||||
<H3><a name="Scripting_nn11"></a>4.3.2 Linking with shared libraries</H3>
|
||||
|
||||
|
||||
<p>
|
||||
|
||||
<a name="n11"></a><H3>3.3.2 Linking with shared libraries</H3>
|
||||
|
||||
|
||||
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>
|
||||
the following :</p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>>>> import graph
|
||||
<blockquote><pre>
|
||||
>>> import graph
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
File "/home/sci/data1/beazley/graph/graph.py", line 2, in ?
|
||||
|
|
@ -396,8 +414,8 @@ lib/libgraph.so:/lib/cmplrs/cc/libgraph.so:/usr/lib/cmplrs/cc/libgraph.so:
|
|||
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>
|
||||
<p>
|
||||
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
|
||||
|
|
@ -417,23 +435,25 @@ the path using linker options instead.
|
|||
|
||||
</ul>
|
||||
|
||||
<a name="n12"></a><H3>3.3.3 Static linking</H3>
|
||||
<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>
|
||||
|
||||
<p><hr>
|
||||
|
||||
<hr>
|
||||
<address>SWIG 1.3 - Last Modified : July 16, 2001</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue