mirror of https://github.com/swig/swig
3457 lines
79 KiB
HTML
3457 lines
79 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>SWIG and Tcl</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<H1><a name="Tcl">37 SWIG and Tcl</a></H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#Tcl_nn2">Preliminaries</a>
|
|
<ul>
|
|
<li><a href="#Tcl_nn3">Getting the right header files</a>
|
|
<li><a href="#Tcl_nn4">Compiling a dynamic module</a>
|
|
<li><a href="#Tcl_nn5">Static linking</a>
|
|
<li><a href="#Tcl_nn6">Using your module</a>
|
|
<li><a href="#Tcl_nn7">Compilation of C++ extensions</a>
|
|
<li><a href="#Tcl_nn8">Compiling for 64-bit platforms</a>
|
|
<li><a href="#Tcl_nn9">Setting a package prefix</a>
|
|
<li><a href="#Tcl_nn10">Using namespaces</a>
|
|
</ul>
|
|
<li><a href="#Tcl_nn11">Building Tcl/Tk Extensions under Windows 95/NT</a>
|
|
<ul>
|
|
<li><a href="#Tcl_nn12">Running SWIG from Developer Studio</a>
|
|
<li><a href="#Tcl_nn13">Using NMAKE</a>
|
|
</ul>
|
|
<li><a href="#Tcl_nn14">A tour of basic C/C++ wrapping</a>
|
|
<ul>
|
|
<li><a href="#Tcl_nn15">Modules</a>
|
|
<li><a href="#Tcl_nn16">Functions</a>
|
|
<li><a href="#Tcl_nn17">Global variables</a>
|
|
<li><a href="#Tcl_nn18">Constants and enums</a>
|
|
<li><a href="#Tcl_nn19">Pointers</a>
|
|
<li><a href="#Tcl_nn20">Structures</a>
|
|
<li><a href="#Tcl_nn21">C++ classes</a>
|
|
<li><a href="#Tcl_nn22">C++ inheritance</a>
|
|
<li><a href="#Tcl_nn23">Pointers, references, values, and arrays</a>
|
|
<li><a href="#Tcl_nn24">C++ overloaded functions</a>
|
|
<li><a href="#Tcl_nn25">C++ operators</a>
|
|
<li><a href="#Tcl_nn26">C++ namespaces</a>
|
|
<li><a href="#Tcl_nn27">C++ templates</a>
|
|
<li><a href="#Tcl_nn28">C++ Smart Pointers</a>
|
|
</ul>
|
|
<li><a href="#Tcl_nn29">Further details on the Tcl class interface</a>
|
|
<ul>
|
|
<li><a href="#Tcl_nn30">Proxy classes</a>
|
|
<li><a href="#Tcl_nn31">Memory management</a>
|
|
</ul>
|
|
<li><a href="#Tcl_nn32">Input and output parameters</a>
|
|
<li><a href="#Tcl_nn33">Exception handling </a>
|
|
<li><a href="#Tcl_nn34">Typemaps</a>
|
|
<ul>
|
|
<li><a href="#Tcl_nn35">What is a typemap?</a>
|
|
<li><a href="#Tcl_nn36">Tcl typemaps</a>
|
|
<li><a href="#Tcl_nn37">Typemap variables</a>
|
|
<li><a href="#Tcl_nn38">Converting a Tcl list to a char ** </a>
|
|
<li><a href="#Tcl_nn39">Returning values in arguments</a>
|
|
<li><a href="#Tcl_nn40">Useful functions</a>
|
|
<li><a href="#Tcl_nn41">Standard typemaps</a>
|
|
<li><a href="#Tcl_nn42">Pointer handling</a>
|
|
</ul>
|
|
<li><a href="#Tcl_nn43">Turning a SWIG module into a Tcl Package.</a>
|
|
<li><a href="#Tcl_nn44">Building new kinds of Tcl interfaces (in Tcl)</a>
|
|
<ul>
|
|
<li><a href="#Tcl_nn45">Proxy classes</a>
|
|
</ul>
|
|
<li><a href="#Tcl_nn46">Tcl/Tk Stubs</a>
|
|
</ul>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<p>
|
|
<b>Caution: This chapter is under repair!</b>
|
|
</p>
|
|
|
|
<p>
|
|
This chapter discusses SWIG's support of Tcl. Since SWIG 4.1.0, Tcl 8.4 or a
|
|
later release is required. Prior to that earlier Tcl 8.x releases were also
|
|
supported.
|
|
</p>
|
|
|
|
<H2><a name="Tcl_nn2">37.1 Preliminaries</a></H2>
|
|
|
|
|
|
<p>
|
|
To build a Tcl module, run SWIG using the <tt>-tcl</tt> or <tt>-tcl8</tt> option :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$ swig -tcl example.i
|
|
</pre></div>
|
|
|
|
<p>
|
|
If building a C++ extension, add the <tt>-c++</tt> option:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$ swig -c++ -tcl example.i
|
|
</pre></div>
|
|
|
|
<p>
|
|
This creates a file <tt>example_wrap.c</tt> or
|
|
<tt>example_wrap.cxx</tt> that contains all of the code needed to
|
|
build a Tcl extension module. To finish building the module, you
|
|
need to compile this file and link it with the rest of your program.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn3">37.1.1 Getting the right header files</a></H3>
|
|
|
|
|
|
<p>
|
|
In order to compile the wrapper code, the compiler needs the <tt>tcl.h</tt> header file.
|
|
This file is usually contained in the directory
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
/usr/local/include
|
|
</pre></div>
|
|
|
|
<p>
|
|
Be aware that some Tcl versions install this header file with a version number attached to it. If
|
|
this is the case, you should probably make a symbolic link so that <tt>tcl.h</tt> points to the correct
|
|
header file.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn4">37.1.2 Compiling a dynamic module</a></H3>
|
|
|
|
|
|
<p>
|
|
The preferred approach to building an extension module is to compile it into
|
|
a shared object file or DLL. Assuming you have code you need to link to in a file
|
|
called <tt>example.c</tt>, you will need to compile your program
|
|
using commands like this (shown for Linux):
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$ swig -tcl example.i
|
|
$ gcc -fPIC -c example.c
|
|
$ gcc -fPIC -c example_wrap.c -I/usr/local/include
|
|
$ gcc -shared example.o example_wrap.o -o example.so
|
|
</pre></div>
|
|
|
|
<p>
|
|
The exact commands for doing this 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/tcl</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="https://github.com/swig/swig/wiki">SWIG Wiki</a> for
|
|
additional information.
|
|
</p>
|
|
|
|
<p>
|
|
When linking the module, the name of the output file has to match the name
|
|
of the module. If the name of your SWIG module is "<tt>example</tt>", the
|
|
name of the corresponding object file should be
|
|
"<tt>example.so</tt>".
|
|
The name of the module is specified using the <tt>%module</tt> directive or the
|
|
<tt>-module</tt> command line option.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn5">37.1.3 Static linking</a></H3>
|
|
|
|
|
|
<p>
|
|
An alternative approach to dynamic linking is to rebuild the Tcl
|
|
interpreter with your extension module added to it. In the past,
|
|
this approach was sometimes necessary due to limitations in dynamic loading
|
|
support on certain machines. However, the situation has improved greatly
|
|
over the last few years and you should not consider this approach
|
|
unless there is really no other option.
|
|
</p>
|
|
|
|
<p>
|
|
The usual procedure for adding a new module to Tcl involves writing a
|
|
special function <tt>Tcl_AppInit()</tt> and using it to initialize the interpreter and
|
|
your module. With SWIG, the <tt>tclsh.i</tt> and <tt>wish.i</tt> library files
|
|
can be used to rebuild the <tt>tclsh</tt> and <tt>wish</tt> interpreters respectively.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
|
|
%inline %{
|
|
extern int fact(int);
|
|
extern int mod(int, int);
|
|
extern double My_variable;
|
|
%}
|
|
|
|
%include "tclsh.i" // Include code for rebuilding tclsh
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
The <tt>tclsh.i</tt> library file includes supporting code that
|
|
contains everything needed to rebuild tclsh. To rebuild the interpreter,
|
|
you simply do something like this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$ swig -tcl example.i
|
|
$ gcc example.c example_wrap.c \
|
|
-Xlinker -export-dynamic \
|
|
-DHAVE_CONFIG_H -I/usr/local/include/ \
|
|
-L/usr/local/lib -ltcl -lm -ldl \
|
|
-o mytclsh
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
You will need to supply the same libraries that were used to build Tcl the first
|
|
time. This may include system libraries such as <tt>-lsocket</tt>, <tt>-lnsl</tt>,
|
|
and <tt>-lpthread</tt>. If this actually works, the new version of Tcl
|
|
should be identical to the default version except that your extension module will be
|
|
a built-in part of the interpreter.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Comment:</b> In practice, you should probably try to avoid static
|
|
linking if possible. Some programmers may be inclined
|
|
to use static linking in the interest of getting better performance.
|
|
However, the performance gained by static linking tends to be rather
|
|
minimal in most situations (and quite frankly not worth the extra
|
|
hassle in the opinion of this author).
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn6">37.1.4 Using your module</a></H3>
|
|
|
|
|
|
<p>
|
|
To use your module, simply use the Tcl <tt>load</tt> command. If
|
|
all goes well, you will be able to this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$ tclsh
|
|
% load ./example.so
|
|
% fact 4
|
|
24
|
|
%
|
|
</pre></div>
|
|
|
|
<p>
|
|
A common error received by first-time users is the following:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./example.so
|
|
couldn't find procedure Example_Init
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This error is almost always caused when the name of the shared object file doesn't
|
|
match the name of the module supplied using the SWIG <tt>%module</tt> directive.
|
|
Double-check the interface to make sure the module name and the shared object
|
|
file match. Another possible cause of this error is forgetting to link the SWIG-generated
|
|
wrapper code with the rest of your application when creating the extension module.
|
|
</p>
|
|
|
|
<p>
|
|
Another common error is something similar to the following:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./example.so
|
|
couldn't load file "./example.so": ./example.so: undefined symbol: fact
|
|
%
|
|
</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.
|
|
</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
|
|
problem when you try to use your module:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./example.so
|
|
couldn't load file "./example.so": libfoo.so: cannot open shared object file:
|
|
No such file or directory
|
|
%
|
|
</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 fix this problem,
|
|
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 \
|
|
-Xlinker -rpath /home/beazley/projects/lib \
|
|
-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 Tcl, you might want to do this instead:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
$ env LD_LIBRARY_PATH=/home/beazley/projects/lib tclsh
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Finally, you can use a command such as <tt>ldconfig</tt> 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="Tcl_nn7">37.1.5 Compilation of C++ extensions</a></H3>
|
|
|
|
|
|
<p>
|
|
Compilation of C++ extensions has traditionally been a tricky problem.
|
|
Since the Tcl 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++ -tcl example.i
|
|
% g++ -fPIC -c example.cxx
|
|
% g++ -fPIC -c example_wrap.cxx -I/usr/local/include
|
|
% g++ -shared example.o example_wrap.o -o example.so
|
|
</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++ -tcl example.i
|
|
% CC -KPIC -c example.cxx
|
|
% CC -KPIC -c example_wrap.cxx -I/usr/local/include
|
|
% CC -G example.o example_wrap.o -L/opt/SUNWspro/lib -o example.so -lCrun
|
|
</pre></div>
|
|
|
|
<p>
|
|
Of course, the extra libraries to use are completely non-portable---you will
|
|
probably need to do some experimentation.
|
|
</p>
|
|
|
|
<p>
|
|
Sometimes people have suggested that it is necessary to relink the
|
|
Tcl 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. 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 Tcl.
|
|
</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:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
$ ldd swig
|
|
libstdc++-libc6.1-1.so.2 => /usr/lib/libstdc++-libc6.1-1.so.2 (0x40019000)
|
|
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>
|
|
As a final complication, a major weakness 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 Tcl, 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. If working with lots of software components, you
|
|
might want to investigate using a more formal standard such as COM.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn8">37.1.6 Compiling for 64-bit platforms</a></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 Tcl 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>
|
|
|
|
<H3><a name="Tcl_nn9">37.1.7 Setting a package prefix</a></H3>
|
|
|
|
|
|
<p>
|
|
To avoid namespace problems, you can instruct SWIG to append a package
|
|
prefix to all of your functions and variables. This is done using the
|
|
-prefix option as follows :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
swig -tcl -prefix Foo example.i
|
|
</pre></div>
|
|
|
|
<p>
|
|
If you have a function "<tt>bar</tt>" in the SWIG file, the prefix
|
|
option will append the prefix to the name when creating a command and
|
|
call it "<tt>Foo_bar</tt>".
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn10">37.1.8 Using namespaces</a></H3>
|
|
|
|
|
|
<p>
|
|
Alternatively, you can have SWIG install your module into a Tcl
|
|
namespace by specifying the <tt>-namespace</tt> option :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
swig -tcl -namespace example.i
|
|
</pre></div>
|
|
|
|
<p>
|
|
By default, the name of the namespace will be the same as the module
|
|
name, but you can override it using the <tt>-prefix</tt> option.
|
|
</p>
|
|
|
|
<p>
|
|
When the <tt>-namespace</tt> option is used, objects in the module
|
|
are always accessed with the namespace name such as <tt>Foo::bar</tt>.
|
|
</p>
|
|
|
|
<H2><a name="Tcl_nn11">37.2 Building Tcl/Tk Extensions under Windows 95/NT</a></H2>
|
|
|
|
|
|
<p>
|
|
Building a SWIG extension to Tcl/Tk under Windows 95/NT is roughly
|
|
similar to the process used with Unix. Normally, you will want to
|
|
produce a DLL that can be loaded into tclsh or wish. This section
|
|
covers the process of using SWIG with Microsoft Visual C++.
|
|
although the procedure may be similar with other compilers.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn12">37.2.1 Running SWIG from Developer Studio</a></H3>
|
|
|
|
|
|
<p>
|
|
If you are developing your application within Microsoft developer
|
|
studio, SWIG can be invoked as a custom build option. The process
|
|
roughly follows 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 -tcl -o $(ProjDir)\$(InputName)_wrap.c
|
|
$(InputPath)</tt>" in the "Build command(s) field"
|
|
|
|
<li>Enter "<tt>$(ProjDir)\$(InputName)_wrap.c</tt>" 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 Tcl
|
|
installation under "Additional include directories".
|
|
|
|
<li>Finally, select the settings for the entire project and go to
|
|
"Link Options". Add the Tcl library file to your link libraries. For
|
|
example "<tt>tcl80.lib</tt>". Also, set the name of the output file
|
|
to match the name of your Tcl module (ie. example.dll).
|
|
|
|
<li>Build your project.
|
|
</ul>
|
|
|
|
<p>
|
|
Now, assuming all went well, 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 Tcl extension, simply run
|
|
<tt>tclsh</tt> or <tt>wish</tt> and use the <tt>load</tt> command.
|
|
For example :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
MSDOS > tclsh80
|
|
% load example.dll
|
|
% fact 4
|
|
24
|
|
%
|
|
</pre></div>
|
|
|
|
<H3><a name="Tcl_nn13">37.2.2 Using NMAKE</a></H3>
|
|
|
|
|
|
<p>
|
|
Alternatively, SWIG extensions can be built by writing a Makefile for
|
|
NMAKE. To do this, make sure the environment variables for MSVC++ are
|
|
available and the MSVC++ tools are in your path. Now, just write a
|
|
short Makefile like this :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
# Makefile for building various SWIG generated extensions
|
|
|
|
SRCS = example.c
|
|
IFILE = example
|
|
INTERFACE = $(IFILE).i
|
|
WRAPFILE = $(IFILE)_wrap.c
|
|
|
|
# Location of the Visual C++ tools (32 bit assumed)
|
|
|
|
TOOLS = c:\msdev
|
|
TARGET = example.dll
|
|
CC = $(TOOLS)\bin\cl.exe
|
|
LINK = $(TOOLS)\bin\link.exe
|
|
INCLUDE32 = -I$(TOOLS)\include
|
|
MACHINE = IX86
|
|
|
|
# C Library needed to build a DLL
|
|
|
|
DLLIBC = msvcrt.lib oldnames.lib
|
|
|
|
# Windows libraries that are apparently needed
|
|
WINLIB = kernel32.lib advapi32.lib user32.lib gdi32.lib comdlg32.lib
|
|
winspool.lib
|
|
|
|
# Libraries common to all DLLs
|
|
LIBS = $(DLLIBC) $(WINLIB)
|
|
|
|
# Linker options
|
|
LOPT = -debug:full -debugtype:cv /NODEFAULTLIB /RELEASE /NOLOGO /
|
|
MACHINE:$(MACHINE) -entry:_DllMainCRTStartup@12 -dll
|
|
|
|
# C compiler flags
|
|
|
|
CFLAGS = /Z7 /Od /c /nologo
|
|
TCL_INCLUDES = -Id:\tcl8.0a2\generic -Id:\tcl8.0a2\win
|
|
TCLLIB = d:\tcl8.0a2\win\tcl80.lib
|
|
|
|
tcl:
|
|
..\..\swig -tcl -o $(WRAPFILE) $(INTERFACE)
|
|
$(CC) $(CFLAGS) $(TCL_INCLUDES) $(SRCS) $(WRAPFILE)
|
|
set LIB=$(TOOLS)\lib
|
|
$(LINK) $(LOPT) -out:example.dll $(LIBS) $(TCLLIB) example.obj example_wrap.obj
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
To build the extension, run NMAKE (you may need to run vcvars32
|
|
first). This is a pretty minimal Makefile, but hopefully it's enough
|
|
to get you started. With a little practice, you'll be making lots of
|
|
Tcl extensions.
|
|
</p>
|
|
|
|
<H2><a name="Tcl_nn14">37.3 A tour of basic C/C++ wrapping</a></H2>
|
|
|
|
|
|
<p>
|
|
By default, SWIG tries to build a very natural Tcl interface to your
|
|
C/C++ code. Functions are wrapped as functions, classes are wrapped
|
|
in an interface that mimics the style of Tk widgets and [incr Tcl]
|
|
classes. This section briefly covers the essential aspects of this
|
|
wrapping.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn15">37.3.1 Modules</a></H3>
|
|
|
|
|
|
<p>
|
|
The SWIG <tt>%module</tt> directive specifies the name of the Tcl
|
|
module. If you specify `<tt>%module example</tt>', then everything is
|
|
compiled into an extension module <tt>example.so</tt>. When choosing a
|
|
module name, make sure you don't use the same name as a built-in
|
|
Tcl command.
|
|
</p>
|
|
|
|
<p>
|
|
One pitfall to watch out for is module names involving numbers. If
|
|
you specify a module name like <tt>%module md5</tt>, you'll find that the
|
|
load command no longer seems to work:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./md5.so
|
|
couldn't find procedure Md_Init
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To fix this, supply an extra argument to <tt>load</tt> like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./md5.so md5
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn16">37.3.2 Functions</a></H3>
|
|
|
|
|
|
<p>
|
|
Global functions are wrapped as new Tcl built-in commands. For example,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
int fact(int n);
|
|
</pre></div>
|
|
|
|
<p>
|
|
creates a built-in function <tt>fact</tt> that works exactly
|
|
like you think it does:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% load ./example.so
|
|
% fact 4
|
|
24
|
|
% set x [fact 6]
|
|
%
|
|
</pre></div>
|
|
|
|
<H3><a name="Tcl_nn17">37.3.3 Global variables</a></H3>
|
|
|
|
|
|
<p>
|
|
C/C++ global variables are wrapped by Tcl global variables. For example:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
// SWIG interface file with global variables
|
|
%module example
|
|
...
|
|
%inline %{
|
|
extern double density;
|
|
%}
|
|
...
|
|
</pre></div>
|
|
|
|
<p>
|
|
Now look at the Tcl interface:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% puts $density # Output value of C global variable
|
|
1.0
|
|
% set density 0.95 # Change value
|
|
</pre></div>
|
|
|
|
<p>
|
|
If you make an error in variable assignment, you will get an
|
|
error message. For example:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% set density "hello"
|
|
can't set "density": Type error. expected a double.
|
|
%
|
|
</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 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>
|
|
If you just want to make a specific variable immutable, supply a declaration name. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%{
|
|
extern char *path;
|
|
%}
|
|
%immutable path;
|
|
...
|
|
extern char *path; // Read-only (due to %immutable)
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn18">37.3.4 Constants and enums</a></H3>
|
|
|
|
|
|
<p>
|
|
C/C++ constants are installed as global Tcl variables containing the
|
|
appropriate value. To create a constant, use <tt>#define</tt>, <tt>enum</tt>, or the
|
|
<tt>%constant</tt> directive. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
#define PI 3.14159
|
|
#define VERSION "1.0"
|
|
|
|
enum Beverage { ALE, LAGER, STOUT, PILSNER };
|
|
|
|
%constant int FOO = 42;
|
|
%constant const char *path = "/usr/local";
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
For enums, make sure that the definition of the enumeration actually appears in a header
|
|
file or in the wrapper file somehow---if you just stick an enum in a SWIG interface without
|
|
also telling the C compiler about it, the wrapper code won't compile.
|
|
</p>
|
|
|
|
<p>
|
|
Note: declarations declared as <tt>const</tt> are wrapped as read-only variables and
|
|
will be accessed using the <tt>cvar</tt> object described in the previous section. They
|
|
are not wrapped as constants. For further discussion about this, see the <a href="SWIG.html#SWIG">SWIG Basics</a> chapter.
|
|
</p>
|
|
|
|
<p>
|
|
Constants are not guaranteed to remain constant in Tcl---the value
|
|
of the constant could be accidentally reassigned.You will just have to be careful.
|
|
</p>
|
|
|
|
<p>
|
|
A peculiarity of installing constants as variables is that it is necessary to use the Tcl <tt>global</tt> statement to
|
|
access constants in procedure bodies. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
proc blah {} {
|
|
global FOO
|
|
bar $FOO
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If a program relies on a lot of constants, this can be extremely annoying. To fix the problem, consider using the
|
|
following typemap rule:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%apply int CONSTANT { int x };
|
|
#define FOO 42
|
|
...
|
|
void bar(int x);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When applied to an input argument, the <tt>CONSTANT</tt> rule allows a constant to be passed to a function using
|
|
its actual value or a symbolic identifier name. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
proc blah {} {
|
|
bar FOO
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When an identifier name is given, it is used to perform an implicit hash-table lookup of the value during argument
|
|
conversion. This allows the <tt>global</tt> statement to be omitted.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn19">37.3.5 Pointers</a></H3>
|
|
|
|
|
|
<p>
|
|
C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with
|
|
incomplete type information. Here is a rather simple interface:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%module example
|
|
|
|
FILE *fopen(const char *filename, const char *mode);
|
|
int fputs(const char *, FILE *);
|
|
int fclose(FILE *);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When wrapped, you will be able to use the functions in a natural way from Tcl.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./example.so
|
|
% set f [fopen junk w]
|
|
% fputs "Hello World\n" $f
|
|
% fclose $f
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If this makes you uneasy, rest assured that there is no
|
|
deep magic involved. Underneath the covers, pointers to C/C++ objects are
|
|
simply represented as opaque values--normally an encoded character
|
|
string like this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% puts $f
|
|
_c0671108_p_FILE
|
|
%
|
|
</pre></div>
|
|
|
|
<p>
|
|
This pointer value can be freely passed around to different C functions that
|
|
expect to receive an object of type <tt>FILE *</tt>. The only thing you can't do is
|
|
dereference the pointer from Tcl.
|
|
</p>
|
|
|
|
<p>
|
|
The NULL pointer is represented by the string <tt>NULL</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
As much as you might be inclined to modify a pointer value directly
|
|
from Tcl, don't. The hexadecimal encoding is not necessarily the
|
|
same as the logical memory address of the underlying object. Instead
|
|
it is the raw byte encoding of the pointer value. The encoding will
|
|
vary depending on the native byte-ordering of the platform (i.e.,
|
|
big-endian vs. little-endian). Similarly, don't try to manually cast
|
|
a pointer to a new type by simply replacing the type-string. 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>None</tt> if the conversion can't be performed.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn20">37.3.6 Structures</a></H3>
|
|
|
|
|
|
<p>
|
|
If you wrap a C structure, it is wrapped by a Tcl interface that somewhat resembles a Tk widget.
|
|
This provides a very natural interface. For example,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
struct Vector {
|
|
double x, y, z;
|
|
};
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
is used as follows:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% Vector v
|
|
% v configure -x 3.5 -y 7.2
|
|
% puts "[v cget -x] [v cget -y] [v cget -z]"
|
|
3.5 7.2 0.0
|
|
%
|
|
</pre></div>
|
|
|
|
<p>
|
|
Similar access is provided for unions and the data members of C++ classes.
|
|
</p>
|
|
|
|
<p>
|
|
In the above example, <tt>v</tt> is a name that's used for the object. However,
|
|
underneath the covers, there's a pointer to a raw C structure. This can be obtained
|
|
by looking at the <tt>-this</tt> attribute. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% puts [v cget -this]
|
|
_88e31408_p_Vector
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Further details about the relationship between the Tcl and the underlying C structure
|
|
are covered a little later.
|
|
</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>
|
|
If a structure contains arrays, access to those arrays is managed through pointers. For
|
|
example, consider this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
struct Bar {
|
|
int x[16];
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If accessed in Tcl, you will see behavior like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Bar b
|
|
% puts [b cget -x]
|
|
_801861a4_p_int
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This pointer can be passed around to functions that expect to receive
|
|
an <tt>int *</tt> (just like C). You can also set the value of an array member using
|
|
another pointer. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Bar c
|
|
% c configure -x [b cget -x] # Copy contents of b.x to c.x
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
For array assignment, SWIG copies the entire contents of the array starting with the data pointed
|
|
to by <tt>b.x</tt>. In this example, 16 integers would be copied. Like C, SWIG makes
|
|
no assumptions about bounds checking---if you pass a bad pointer, you may get a segmentation
|
|
fault or access violation.
|
|
</p>
|
|
|
|
<p>
|
|
When a member of a structure is itself a structure, it is handled as a
|
|
pointer. For example, suppose you have two structures like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
struct Foo {
|
|
int a;
|
|
};
|
|
|
|
struct Bar {
|
|
Foo f;
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Now, suppose that you access the <tt>f</tt> attribute of <tt>Bar</tt> like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Bar b
|
|
% set x [b cget -f]
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, <tt>x</tt> is a pointer that points to the <tt>Foo</tt> that is inside <tt>b</tt>.
|
|
This is the same value as generated by this C code:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Bar b;
|
|
Foo *x = &b->f; /* Points inside b */
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
However, one peculiarity of accessing a substructure like this is that the returned
|
|
value does work quite like you might expect. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Bar b
|
|
% set x [b cget -f]
|
|
% x cget -a
|
|
invalid command name "x"
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This is because the returned value was not created in a normal way from the interpreter (x is
|
|
not a command object). To make it function normally, just
|
|
evaluate the variable like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Bar b
|
|
% set x [b cget -f]
|
|
% $x cget -a
|
|
0
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this example, <tt>x</tt> points inside the original structure. This means that modifications
|
|
work just like you would expect. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
|
|
% Bar b
|
|
% set x [b cget -f]
|
|
% $x configure -a 3 # Modifies contents of f (inside b)
|
|
% [b cget -f] -configure -a 3 # Same thing
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In many of these structure examples, a simple name like "v" or "b" has been given
|
|
to wrapped structures. If necessary, this name can be passed to functions
|
|
that expect to receive an object. For example, if you have a function like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void blah(Foo *f);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
you can call the function in Tcl as follows:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo x # Create a Foo object
|
|
% blah x # Pass the object to a function
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It is also possible to call the function using the raw pointer value. For
|
|
instance:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% blah [x cget -this] # Pass object to a function
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It is also possible to create and use objects using variables. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% set b [Bar] # Create a Bar
|
|
% $b cget -f # Member access
|
|
% puts $b
|
|
_108fea88_p_Bar
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Finally, to destroy objects created from Tcl, you can either let the object
|
|
name go out of scope or you can explicitly delete the object as shown below.
|
|
Objects won't get automatically destroyed when the Tcl program exits, so if
|
|
it's important that the C++ destructor is called for a class you'll need to
|
|
make sure that you explicitly do this for objects of that class before program
|
|
exit.
|
|
</p>
|
|
|
|
<p>
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f # Create object f
|
|
% rename f ""
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
or
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f # Create object f
|
|
% f -delete
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Note: Tcl only destroys the underlying object if it has ownership. See the
|
|
memory management section that appears shortly.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn21">37.3.7 C++ classes</a></H3>
|
|
|
|
|
|
<p>
|
|
C++ classes are wrapped as an extension of structure wrapping. For example, if you have this 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;
|
|
};
|
|
</pre></div>
|
|
|
|
<p>
|
|
you can use it in Tcl like this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% List x
|
|
% x insert Ale
|
|
% x insert Stout
|
|
% x insert Lager
|
|
% x get 1
|
|
Stout
|
|
% puts [x cget -length]
|
|
3
|
|
%
|
|
</pre></div>
|
|
|
|
<p>
|
|
Class data members are accessed in the same manner as C structures.
|
|
</p>
|
|
|
|
<p>
|
|
Static class members are accessed as global functions or variables.
|
|
To illustrate, suppose you have a class like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Spam {
|
|
public:
|
|
static void foo();
|
|
static int bar;
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In Tcl, the static member is accessed as follows:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Spam_foo # Spam::foo()
|
|
% puts $Spam_bar # Spam::bar
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn22">37.3.8 C++ inheritance</a></H3>
|
|
|
|
|
|
<p>
|
|
SWIG is fully aware of issues related to C++ inheritance. Therefore, if you have
|
|
classes like this
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
...
|
|
};
|
|
|
|
class Bar : public Foo {
|
|
...
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
An object of type <tt>Bar</tt> can be used where a <tt>Foo</tt> is expected. For
|
|
example, if you have this function:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void spam(Foo *f);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then the function <tt>spam()</tt> accepts a <tt>Foo *</tt> or a pointer to any class derived from <tt>Foo</tt>.
|
|
For instance:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f # Create a Foo
|
|
% Bar b # Create a Bar
|
|
% spam f # OK
|
|
% spam b # OK
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It is safe to use multiple inheritance with SWIG.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn23">37.3.9 Pointers, references, values, and arrays</a></H3>
|
|
|
|
|
|
<p>
|
|
In C++, there are many different ways a function might receive
|
|
and manipulate objects. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void spam1(Foo *x); // Pass by pointer
|
|
void spam2(Foo &x); // Pass by reference
|
|
void spam3(Foo x); // Pass by value
|
|
void spam4(Foo x[]); // Array of objects
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In Tcl, there is no detailed distinction like this.
|
|
Because of this, SWIG unifies all of these types
|
|
together in the wrapper code. For instance, if you actually had the
|
|
above functions, it is perfectly legal to do this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f # Create a Foo
|
|
% spam1 f # Ok. Pointer
|
|
% spam2 f # Ok. Reference
|
|
% spam3 f # Ok. Value.
|
|
% spam4 f # Ok. Array (1 element)
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Similar behavior occurs for return values. For example, if you had
|
|
functions like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Foo *spam5();
|
|
Foo &spam6();
|
|
Foo spam7();
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then all three functions will return a pointer to some <tt>Foo</tt> object.
|
|
Since the third function (spam7) returns a value, newly allocated memory is used
|
|
to hold the result and a pointer is returned (Tcl will release this memory
|
|
when the return value is garbage collected).
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn24">37.3.10 C++ overloaded functions</a></H3>
|
|
|
|
|
|
<p>
|
|
C++ overloaded functions, methods, and constructors are mostly supported by SWIG. For example,
|
|
if you have two functions like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void foo(int);
|
|
void foo(char *c);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
You can use them in Tcl in a straightforward manner:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% foo 3 # foo(int)
|
|
% foo Hello # foo(char *c)
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Similarly, if you have a class like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
public:
|
|
Foo();
|
|
Foo(const Foo &);
|
|
...
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
you can write Tcl code like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f # Create a Foo
|
|
% Foo g f # Copy f
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Overloading support is not quite as flexible as in C++. Sometimes there are methods that SWIG
|
|
can't disambiguate. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void spam(int);
|
|
void spam(short);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
or
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void foo(Bar *b);
|
|
void foo(Bar &b);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If declarations such as these appear, you will get a warning message like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
example.i:12: Warning 509: Overloaded method spam(short) effectively ignored,
|
|
example.i:11: Warning 509: as it is shadowed by spam(int).
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To fix this, you either need to ignore or rename one of the methods. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%rename(spam_short) spam(short);
|
|
...
|
|
void spam(int);
|
|
void spam(short); // Accessed as spam_short
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
or
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%ignore spam(short);
|
|
...
|
|
void spam(int);
|
|
void spam(short); // Ignored
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
SWIG resolves overloaded functions and methods using a disambiguation scheme that ranks and sorts
|
|
declarations according to a set of type-precedence rules. The order in which declarations appear
|
|
in the input does not matter except in situations where ambiguity arises--in this case, the
|
|
first declaration takes precedence.
|
|
</p>
|
|
|
|
<p>
|
|
Please refer to the "SWIG and C++" chapter for more information about overloading.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn25">37.3.11 C++ operators</a></H3>
|
|
|
|
|
|
<p>
|
|
Certain C++ overloaded operators can be handled automatically by SWIG. For example,
|
|
consider a class like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Complex {
|
|
private:
|
|
double rpart, ipart;
|
|
public:
|
|
Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { }
|
|
Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { }
|
|
Complex &operator=(const Complex &c);
|
|
Complex operator+(const Complex &c) const;
|
|
Complex operator-(const Complex &c) const;
|
|
Complex operator*(const Complex &c) const;
|
|
Complex operator-() const;
|
|
|
|
double re() const { return rpart; }
|
|
double im() const { return ipart; }
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When wrapped, it works like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Complex c 3 4
|
|
% Complex d 7 8
|
|
% set e [c + d]
|
|
% $e re
|
|
10.0
|
|
% $e im
|
|
12.0
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It should be stressed that operators in SWIG have no relationship to operators
|
|
in Tcl. In fact, the only thing that's happening here is that an operator like
|
|
<tt>operator +</tt> has been renamed to a method <tt>+</tt>. Therefore, the
|
|
statement <tt>[c + d]</tt> is really just invoking the <tt>+</tt> method on <tt>c</tt>.
|
|
When more than operator is defined (with different arguments), the standard
|
|
method overloading facilities are used. Here is a rather odd looking example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Complex c 3 4
|
|
% Complex d 7 8
|
|
% set e [c - d] # operator-(const Complex &)
|
|
% puts "[$e re] [$e im]"
|
|
10.0 12.0
|
|
% set f [c -] # operator-()
|
|
% puts "[$f re] [$f im]"
|
|
-3.0 -4.0
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
One restriction with operator overloading support is that SWIG is not
|
|
able to fully handle operators that aren't defined as part of the class.
|
|
For example, if you had code like this
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Complex {
|
|
...
|
|
friend Complex operator+(double, const Complex &c);
|
|
...
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then SWIG doesn't know what to do with the friend function--in fact,
|
|
it simply ignores it and issues a warning. You can still wrap the operator,
|
|
but you may have to encapsulate it in a special function. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%rename(Complex_add_dc) operator+(double, const Complex &);
|
|
...
|
|
Complex operator+(double, const Complex &c);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
There are ways to make this operator appear as part of the class using the <tt>%extend</tt> directive.
|
|
Keep reading.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn26">37.3.12 C++ namespaces</a></H3>
|
|
|
|
|
|
<p>
|
|
SWIG is aware of C++ namespaces, but namespace names do not appear in
|
|
the module nor do namespaces result in a module that is broken up into
|
|
submodules or packages. For example, if you have a file like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%module example
|
|
|
|
namespace foo {
|
|
int fact(int n);
|
|
struct Vector {
|
|
double x, y, z;
|
|
};
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
it works in Tcl as follows:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./example.so
|
|
% fact 3
|
|
6
|
|
% Vector v
|
|
% v configure -x 3.4
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If your program has more than one namespace, name conflicts (if any) can be resolved using <tt>%rename</tt>
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%rename(Bar_spam) Bar::spam;
|
|
|
|
namespace Foo {
|
|
int spam();
|
|
}
|
|
|
|
namespace Bar {
|
|
int spam();
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you have more than one namespace and your want to keep their
|
|
symbols separate, consider wrapping them as separate SWIG modules.
|
|
For example, make the module name the same as the namespace and create
|
|
extension modules for each namespace separately. If your program
|
|
utilizes thousands of small deeply nested namespaces each with
|
|
identical symbol names, well, then you get what you deserve.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn27">37.3.13 C++ templates</a></H3>
|
|
|
|
|
|
<p>
|
|
C++ templates don't present a huge problem for SWIG. However, in order
|
|
to create wrappers, you have to tell SWIG to create wrappers for a particular
|
|
template instantiation. To do this, you use the <tt>%template</tt> directive.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%module example
|
|
%{
|
|
#include "pair.h"
|
|
%}
|
|
|
|
template<class T1, class T2>
|
|
struct pair {
|
|
typedef T1 first_type;
|
|
typedef T2 second_type;
|
|
T1 first;
|
|
T2 second;
|
|
pair();
|
|
pair(const T1&, const T2&);
|
|
~pair();
|
|
};
|
|
|
|
%template(pairii) pair<int, int>;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In Tcl:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% pairii p 3 4
|
|
% p cget -first
|
|
3
|
|
% p cget -second
|
|
4
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Obviously, there is more to template wrapping than shown in this example.
|
|
More details can be found in the <a href="SWIGPlus.html#SWIGPlus">SWIG and C++</a> chapter. Some more complicated
|
|
examples will appear later.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn28">37.3.14 C++ Smart Pointers</a></H3>
|
|
|
|
|
|
<p>
|
|
In certain C++ programs, it is common to use classes that have been wrapped by
|
|
so-called "smart pointers." Generally, this involves the use of a template class
|
|
that implements <tt>operator->()</tt> like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
template<class T> class SmartPtr {
|
|
...
|
|
T *operator->();
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Then, if you have a class like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
public:
|
|
int x;
|
|
int bar();
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
A smart pointer would be used in C++ as follows:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
SmartPtr<Foo> p = CreateFoo(); // Created somehow (not shown)
|
|
...
|
|
p->x = 3; // Foo::x
|
|
int y = p->bar(); // Foo::bar
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To wrap this in Tcl, simply tell SWIG about the <tt>SmartPtr</tt> class and the low-level
|
|
<tt>Foo</tt> object. Make sure you instantiate <tt>SmartPtr</tt> using <tt>%template</tt> if necessary.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%module example
|
|
...
|
|
%template(SmartPtrFoo) SmartPtr<Foo>;
|
|
...
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Now, in Tcl, everything should just "work":
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% set p [CreateFoo] # Create a smart-pointer somehow
|
|
% $p configure -x 3 # Foo::x
|
|
% $p bar # Foo::bar
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you ever need to access the underlying pointer returned by <tt>operator->()</tt> itself,
|
|
simply use the <tt>__deref__()</tt> method. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% set f [$p __deref__] # Returns underlying Foo *
|
|
</pre>
|
|
</div>
|
|
|
|
<H2><a name="Tcl_nn29">37.4 Further details on the Tcl class interface</a></H2>
|
|
|
|
|
|
<p>
|
|
In the previous section, a high-level view of Tcl wrapping was
|
|
presented. A key component of this wrapping is that structures and
|
|
classes are wrapped by Tcl class-like objects. This provides a very
|
|
natural Tcl interface and allows SWIG to support a number of
|
|
advanced features such as operator overloading. However, a number
|
|
of low-level details were omitted. This section provides a brief overview
|
|
of how the proxy classes work.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn30">37.4.1 Proxy classes</a></H3>
|
|
|
|
|
|
<p>
|
|
In the <a href="SWIG.html#SWIG">"SWIG basics"</a> and <a href="SWIGPlus.html#SWIGPlus">"SWIG and C++"</a> chapters,
|
|
details of low-level structure and class wrapping are described. To summarize those chapters, if you
|
|
have a class like this
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
public:
|
|
int x;
|
|
int spam(int);
|
|
...
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then SWIG transforms it into a set of low-level procedural wrappers. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Foo *new_Foo() {
|
|
return new Foo();
|
|
}
|
|
void delete_Foo(Foo *f) {
|
|
delete f;
|
|
}
|
|
int Foo_x_get(Foo *f) {
|
|
return f->x;
|
|
}
|
|
void Foo_x_set(Foo *f, int value) {
|
|
f->x = value;
|
|
}
|
|
int Foo_spam(Foo *f, int arg1) {
|
|
return f->spam(arg1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
These wrappers are actually found in the Tcl extension module. For example, you can certainly do this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% load ./example.so
|
|
% set f [new_Foo]
|
|
% Foo_x_get $f
|
|
0
|
|
% Foo_spam $f 3
|
|
1
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
However, in addition to this, the classname <tt>Foo</tt> is used as an object constructor
|
|
function. This allows objects to be encapsulated objects that look a lot like Tk widgets
|
|
as shown in the last section.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn31">37.4.2 Memory management</a></H3>
|
|
|
|
|
|
<p>
|
|
Associated with each wrapped object, is an ownership flag <tt>thisown</tt> The value of this
|
|
flag determines who is responsible for deleting the underlying C++ object. If set to 1,
|
|
the Tcl interpreter destroys the C++ object when the proxy class is
|
|
garbage collected. If set to 0 (or if the attribute is missing), then the destruction
|
|
of the proxy class has no effect on the C++ object.
|
|
</p>
|
|
|
|
<p>
|
|
When an object is created by a constructor or returned by value, Tcl automatically takes
|
|
ownership of the result. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
public:
|
|
Foo();
|
|
Foo bar();
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In Tcl:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f
|
|
% f cget -thisown
|
|
1
|
|
% set g [f bar]
|
|
% $g cget -thisown
|
|
1
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
On the other hand, when pointers are returned to Tcl, there is often no way to know where
|
|
they came from. Therefore, the ownership is set to zero. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
public:
|
|
...
|
|
Foo *spam();
|
|
...
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f
|
|
% set s [f spam]
|
|
% $s cget -thisown
|
|
0
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This behavior is especially important for classes that act as
|
|
containers. For example, if a method returns a pointer to an object
|
|
that is contained inside another object, you definitely don't want
|
|
Tcl to assume ownership and destroy it!
|
|
</p>
|
|
|
|
<p>
|
|
Related to containers, ownership issues can arise whenever an object is assigned to a member
|
|
or global variable. For example, consider this interface:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%module example
|
|
|
|
struct Foo {
|
|
int value;
|
|
Foo *next;
|
|
};
|
|
|
|
Foo *head = 0;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When wrapped in Tcl, careful observation will reveal that ownership changes whenever an object
|
|
is assigned to a global variable. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f
|
|
% f cget -thisown
|
|
1
|
|
% set head f
|
|
% f cget -thisown
|
|
0
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, C is now holding a reference to the object---you probably don't want Tcl to destroy it.
|
|
Similarly, this occurs for members. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Foo f
|
|
% Foo g
|
|
% f cget -thisown
|
|
1
|
|
% g cget -thisown
|
|
1
|
|
% f configure -next g
|
|
% g cget -thisown
|
|
0
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
For the most part, memory management issues remain hidden. However,
|
|
there are occasionally situations where you might have to manually
|
|
change the ownership of an object. For instance, consider code like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Node {
|
|
Object *value;
|
|
public:
|
|
void set_value(Object *v) { value = v; }
|
|
...
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Now, consider the following Tcl code:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% Object v # Create an object
|
|
% Node n # Create a node
|
|
% n setvalue v # Set value
|
|
% v cget -thisown
|
|
1
|
|
%
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, the object <tt>n</tt> is holding a reference to
|
|
<tt>v</tt> internally. However, SWIG has no way to know that this
|
|
has occurred. Therefore, Tcl still thinks that it has ownership of the
|
|
object. Should the proxy object be destroyed, then the C++ destructor
|
|
will be invoked and <tt>n</tt> will be holding a stale-pointer. If
|
|
you're lucky, you will only get a segmentation fault.
|
|
</p>
|
|
|
|
<p>
|
|
To work around this, it is always possible to flip the ownership flag. For example,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% v -disown # Give ownership to C/C++
|
|
% v -acquire # Acquire ownership
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It is also possible to deal with situations like this using
|
|
typemaps--an advanced topic discussed later.
|
|
</p>
|
|
|
|
|
|
<H2><a name="Tcl_nn32">37.5 Input and output parameters</a></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 Tcl, this allows you to pass simple values instead of pointer. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
set a [add 3 4]
|
|
puts $a
|
|
7
|
|
</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 Tcl, a mutated parameter shows up as a return value. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
set a [negate 3]
|
|
puts $a
|
|
-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 *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 Tcl, the function will return multiple values as a list.
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
set r [send_message "Hello World"]
|
|
set bytes [lindex $r 0]
|
|
set success [lindex $r 1]
|
|
</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="code">
|
|
<pre>
|
|
set dim [get_dimensions $m]
|
|
set r [lindex $dim 0]
|
|
set c [lindex $dim 1]
|
|
</pre>
|
|
</div>
|
|
|
|
<H2><a name="Tcl_nn33">37.6 Exception handling </a></H2>
|
|
|
|
|
|
<p>
|
|
The <tt>%exception</tt> directive can be used to create a user-definable
|
|
exception handler in charge of converting exceptions in your C/C++
|
|
program into Tcl exceptions. The chapter on customization features
|
|
contains more details, but suppose you extended the array example into
|
|
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>
|
|
The functions associated with this class can throw a C++ range
|
|
exception for an out-of-bounds array access. We can catch this in our
|
|
Tcl extension by specifying the following in an interface file :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%exception {
|
|
try {
|
|
$action // Gets substituted by actual function call
|
|
}
|
|
catch (RangeError) {
|
|
Tcl_SetResult(interp, (char *)"Array index out-of-bounds", TCL_STATIC);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
</pre></div>
|
|
|
|
<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) {
|
|
Tcl_SetResult(interp, (char *)"Array index out-of-bounds", TCL_STATIC);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
|
|
%exception setitem {
|
|
try {
|
|
$action
|
|
}
|
|
catch (RangeError) {
|
|
Tcl_SetResult(interp, (char *)"Array index out-of-bounds", TCL_STATIC);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
</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) {
|
|
Tcl_SetResult(interp, (char *)"Array index out-of-bounds", TCL_STATIC);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
%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>
|
|
|
|
<H2><a name="Tcl_nn34">37.7 Typemaps</a></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 Tcl 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 not 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-Tcl interface.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn35">37.7.1 What is a typemap?</a></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 Tcl to C,
|
|
you might define a typemap like this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
|
|
%typemap(in) int {
|
|
if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR)
|
|
return TCL_ERROR;
|
|
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 of type <tt>Tcl_Obj *</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
When this example is compiled into a Tcl module, it operates as follows:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% load ./example.so
|
|
% fact 6
|
|
Received an integer : 6
|
|
720
|
|
</pre></div>
|
|
|
|
<p>
|
|
In this example, the typemap is applied to all occurrences of the <tt>int</tt> datatype.
|
|
You can refine this by supplying an optional parameter name. For example:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
|
|
%typemap(in) int n {
|
|
if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR)
|
|
return TCL_ERROR;
|
|
printf("n = %d\n", $1);
|
|
}
|
|
%inline %{
|
|
extern int fact(int n);
|
|
%}
|
|
</pre></div>
|
|
|
|
<p>
|
|
In this case, the typemap code is only attached to arguments that exactly match <tt>int n</tt>.
|
|
</p>
|
|
|
|
<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="code">
|
|
<pre>
|
|
%typemap(in) int n {
|
|
if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR)
|
|
return TCL_ERROR;
|
|
printf("n = %d\n", $1);
|
|
}
|
|
%inline %{
|
|
typedef int Integer;
|
|
extern int fact(Integer n); // Above typemap is applied
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
However, 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="code">
|
|
<pre>
|
|
%typemap(in) (char *str, int len) {
|
|
$1 = Tcl_GetStringFromObj($input, &$2);
|
|
};
|
|
|
|
int count(char c, char *str, int len);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When a multi-argument typemap is defined, the arguments are always handled as a single
|
|
Tcl object. This allows the function to be used like this (notice how the length
|
|
parameter is omitted):
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% count e "Hello World"
|
|
1
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn36">37.7.2 Tcl typemaps</a></H3>
|
|
|
|
|
|
<p>
|
|
The previous section illustrated an "in" typemap for converting Tcl objects to C.
|
|
A variety of different typemap methods are defined by the Tcl module. For example,
|
|
to convert a C integer back into a Tcl object, you might define an "out" typemap
|
|
like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out) int {
|
|
Tcl_SetObjResult(interp, Tcl_NewIntObj($1));
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The following list details all of the typemap methods that can be used by the Tcl module:
|
|
</p>
|
|
|
|
<p>
|
|
<tt>%typemap(in)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Converts Tcl objects to input function arguments
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(out)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Converts return value of a C function to a Tcl object
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(varin)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Assigns a C global variable from a Tcl object
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(varout)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Returns a C global variable as a Tcl object
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(freearg)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Cleans up a function argument (if necessary)
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(argout)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Output argument processing
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(ret)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Cleanup of function return values
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(consttab)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Creation of Tcl constants (constant table)
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(constcode)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Creation of Tcl constants (init function)
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(memberin)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Setting of structure/class member data
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(globalin)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Setting of C global variables
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(check)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Checks function input values.
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(default)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Set a default value for an argument (making it optional).
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%typemap(arginit)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Initialize an argument to a value before any conversions occur.
|
|
</div>
|
|
|
|
<p>
|
|
Examples of these methods will appear shortly.
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn37">37.7.3 Typemap variables</a></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 Tcl.
|
|
</div>
|
|
|
|
<p>
|
|
<tt>$input</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
A <tt>Tcl_Obj *</tt> holding a raw Tcl object with an argument or variable value.
|
|
</div>
|
|
|
|
<p>
|
|
<tt>$result</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
A <tt>Tcl_Obj *</tt> that holds the result to be returned to Tcl.
|
|
</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 Tcl name of the wrapper function being created.
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn38">37.7.4 Converting a Tcl list to a char ** </a></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 Tcl list to be
|
|
used as a <tt>char **</tt> object.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module argv
|
|
|
|
// This tells SWIG to treat char ** as a special case
|
|
%typemap(in) char ** {
|
|
Tcl_Obj **listobjv;
|
|
int nitems;
|
|
int i;
|
|
if (Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) {
|
|
return TCL_ERROR;
|
|
}
|
|
$1 = (char **) malloc((nitems+1)*sizeof(char *));
|
|
for (i = 0; i < nitems; i++) {
|
|
$1[i] = Tcl_GetStringFromObj(listobjv[i], 0);
|
|
}
|
|
$1[i] = 0;
|
|
}
|
|
|
|
// This gives SWIG some cleanup code that will get called after the function call
|
|
%typemap(freearg) char ** {
|
|
free($1);
|
|
}
|
|
|
|
// Now a 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;
|
|
}
|
|
%}
|
|
%include "tclsh.i"
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
In Tcl:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% print_args {John Guido Larry}
|
|
argv[0] = John
|
|
argv[1] = Guido
|
|
argv[2] = Larry
|
|
3
|
|
</pre></div>
|
|
|
|
<H3><a name="Tcl_nn39">37.7.5 Returning values in arguments</a></H3>
|
|
|
|
|
|
<p>
|
|
The "argout" typemap can be used to return a value originating from a
|
|
function argument. For example :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
// A typemap defining how to return an argument by appending it to the result
|
|
%typemap(argout) double *outvalue {
|
|
Tcl_Obj *o = Tcl_NewDoubleObj($1);
|
|
Tcl_ListObjAppendElement(interp, $result, o);
|
|
}
|
|
|
|
// A typemap telling SWIG to ignore an argument for input
|
|
// However, we still need to pass a pointer to the C function
|
|
%typemap(in, numinputs=0) double *outvalue (double temp) {
|
|
$1 = &temp;
|
|
}
|
|
|
|
// Now a function returning two values
|
|
int mypow(double a, double b, double *outvalue) {
|
|
if ((a < 0) || (b < 0)) return -1;
|
|
*outvalue = pow(a, b);
|
|
return 0;
|
|
};
|
|
</pre></div>
|
|
|
|
<p>
|
|
When wrapped, SWIG matches the <tt>argout</tt> typemap to the
|
|
"<tt>double *outvalue</tt>" argument. The numinputs=0 specification tells SWIG
|
|
to simply ignore this argument when generating wrapper code. As a
|
|
result, a Tcl function using these typemaps will work like this :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
% mypow 2 3 # Returns two values, a status value and the result
|
|
0 8
|
|
%
|
|
</pre></div>
|
|
|
|
<H3><a name="Tcl_nn40">37.7.6 Useful functions</a></H3>
|
|
|
|
|
|
<p>
|
|
The following tables provide some functions that may be useful in
|
|
writing Tcl typemaps.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Integers</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Tcl_Obj *Tcl_NewIntObj(int Value);
|
|
void Tcl_SetIntObj(Tcl_Obj *obj, int Value);
|
|
int Tcl_GetIntFromObj(Tcl_Interp *, Tcl_Obj *obj, int *ip);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Floating Point</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Tcl_Obj *Tcl_NewDoubleObj(double Value);
|
|
void Tcl_SetDoubleObj(Tcl_Obj *obj, double value);
|
|
int Tcl_GetDoubleFromObj(Tcl_Interp *, Tcl_Obj *o, double *dp);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Strings</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Tcl_Obj *Tcl_NewStringObj(char *str, int len);
|
|
char *Tcl_GetStringFromObj(Tcl_Obj *obj, int *len);
|
|
void Tcl_AppendToObj(Tcl_Obj *obj, char *str, int len);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Lists</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *objv);
|
|
int Tcl_ListObjAppendList(Tcl_Interp *, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr);
|
|
int Tcl_ListObjAppendElement(Tcl_Interp *, Tcl_Obj *listPtr, Tcl_Obj *element);
|
|
int Tcl_ListObjGetElements(Tcl_Interp *, Tcl_Obj *listPtr, int *objcPtr,
|
|
Tcl_Obj ***objvPtr);
|
|
int Tcl_ListObjLength(Tcl_Interp *, Tcl_Obj *listPtr, int *intPtr);
|
|
int Tcl_ListObjIndex(Tcl_Interp *, Tcl_Obj *listPtr, int index,
|
|
Tcl_Obj_Obj **objptr);
|
|
int Tcl_ListObjReplace(Tcl_Interp *, Tcl_Obj *listPtr, int first, int count,
|
|
int objc, Tcl_Obj *objv);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Objects</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *obj);
|
|
void Tcl_IncrRefCount(Tcl_Obj *obj);
|
|
void Tcl_DecrRefCount(Tcl_Obj *obj);
|
|
int Tcl_IsShared(Tcl_Obj *obj);
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn41">37.7.7 Standard typemaps</a></H3>
|
|
|
|
|
|
<p>
|
|
The following typemaps show how to convert a few common kinds of
|
|
objects between Tcl and C (and to give a better idea of how typemaps
|
|
work)
|
|
</p>
|
|
|
|
|
|
<p>
|
|
<b>Integer conversion</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int, short, long {
|
|
int temp;
|
|
if (Tcl_GetIntFromObj(interp, $input, &temp) == TCL_ERROR)
|
|
return TCL_ERROR;
|
|
$1 = ($1_ltype) temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out) int, short, long {
|
|
Tcl_SetIntObj($result, (int) $1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Floating point conversion</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) float, double {
|
|
double temp;
|
|
if (Tcl_GetDoubleFromObj(interp, $input, &temp) == TCL_ERROR)
|
|
return TCL_ERROR;
|
|
$1 = ($1_ltype) temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out) float, double {
|
|
Tcl_SetDoubleObj($result, $1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>String Conversion</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) char * {
|
|
int len;
|
|
$1 = Tcl_GetStringFromObj(interp, &len);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out, noblock=1, fragment="SWIG_FromCharPtr") char *, const char * {
|
|
Tcl_SetObjResult(interp, SWIG_FromCharPtr((const char *)$1));
|
|
}
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Tcl_nn42">37.7.8 Pointer handling</a></H3>
|
|
|
|
|
|
<p>
|
|
SWIG pointers are mapped into Tcl strings containing the
|
|
hexadecimal value and type. The following functions can be used to
|
|
create and read pointer values.
|
|
</p>
|
|
|
|
<p>
|
|
<tt>
|
|
int SWIG_ConvertPtr(Tcl_Obj *obj, void **ptr, swig_type_info *ty, int flags)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Converts a Tcl 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. It is currently
|
|
reserved for future expansion. Returns 0 on success and -1 on error.
|
|
</div>
|
|
|
|
<p>
|
|
<tt>
|
|
Tcl_Obj *SWIG_NewPointerObj(void *ptr, swig_type_info *ty, int flags)</tt>
|
|
</p>
|
|
|
|
<div class="indent">
|
|
Creates a new Tcl pointer object. <tt>ptr</tt> is the pointer to convert, <tt>ty</tt> is the SWIG type descriptor structure that
|
|
describes the type, and <tt>own</tt> is a flag reserved for future expansion.
|
|
</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="indent">
|
|
<pre>
|
|
Foo *f;
|
|
if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
|
|
SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
|
|
}
|
|
|
|
Tcl_Obj *;
|
|
obj = SWIG_NewPointerObj(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="indent">
|
|
<pre>
|
|
%typemap(in) Foo * {
|
|
if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
|
|
SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
|
|
}
|
|
}
|
|
</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="indent">
|
|
<pre>
|
|
%typemap(in) Foo * {
|
|
if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
|
|
SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<H2><a name="Tcl_nn43">37.8 Turning a SWIG module into a Tcl Package.</a></H2>
|
|
|
|
|
|
<p>
|
|
SWIG generates all of the code necessary to create a Tcl extension package.
|
|
To set the package version use the <tt>-pkgversion</tt> option. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
% swig -tcl -pkgversion 2.3 example.i
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
After building the SWIG generated module, you need to execute
|
|
the <tt>pkg_mkIndex</tt> command inside tclsh. For example :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
unix > tclsh
|
|
% pkg_mkIndex . example.so
|
|
% exit
|
|
</pre></div>
|
|
|
|
<p>
|
|
This creates a file "<tt>pkgIndex.tcl</tt>" with information about the
|
|
package. To use your package, you now need to move it to its own
|
|
subdirectory which has the same name as the package. For example :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
./example/
|
|
pkgIndex.tcl # The file created by pkg_mkIndex
|
|
example.so # The SWIG generated module
|
|
</pre></div>
|
|
|
|
<p>
|
|
Finally, assuming that you're not entirely confused at this point,
|
|
make sure that the example subdirectory is visible from the
|
|
directories contained in either the <tt>tcl_library</tt> or
|
|
<tt>auto_path</tt> variables. At this point you're ready to use the
|
|
package as follows :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
unix > tclsh
|
|
% package require example
|
|
% fact 4
|
|
24
|
|
%
|
|
</pre></div>
|
|
|
|
<p>
|
|
If you're working with an example in the current directory and this doesn't work, do this instead :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
unix > tclsh
|
|
% lappend auto_path .
|
|
% package require example
|
|
% fact 4
|
|
24
|
|
</pre></div>
|
|
|
|
<p>
|
|
As a final note, most SWIG examples do not yet use the
|
|
<tt>package</tt> commands. For simple extensions it may be easier just
|
|
to use the <tt>load</tt> command instead.
|
|
</p>
|
|
|
|
<H2><a name="Tcl_nn44">37.9 Building new kinds of Tcl interfaces (in Tcl)</a></H2>
|
|
|
|
|
|
<p>
|
|
One of the most interesting aspects of Tcl and SWIG is that you can
|
|
create entirely new kinds of Tcl interfaces in Tcl using the low-level
|
|
SWIG accessor functions. For example, suppose you had a library of
|
|
helper functions to access arrays :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
/* File : array.i */
|
|
%module array
|
|
|
|
%inline %{
|
|
double *new_double(int size) {
|
|
return (double *) malloc(size*sizeof(double));
|
|
}
|
|
void delete_double(double *a) {
|
|
free(a);
|
|
}
|
|
double get_double(double *a, int index) {
|
|
return a[index];
|
|
}
|
|
void set_double(double *a, int index, double val) {
|
|
a[index] = val;
|
|
}
|
|
int *new_int(int size) {
|
|
return (int *) malloc(size*sizeof(int));
|
|
}
|
|
void delete_int(int *a) {
|
|
free(a);
|
|
}
|
|
int get_int(int *a, int index) {
|
|
return a[index];
|
|
}
|
|
int set_int(int *a, int index, int val) {
|
|
a[index] = val;
|
|
}
|
|
%}
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
While these could be called directly, we could also write a Tcl script
|
|
like this :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
proc Array {type size} {
|
|
set ptr [new_$type $size]
|
|
set code {
|
|
set method [lindex $args 0]
|
|
set parms [concat $ptr [lrange $args 1 end]]
|
|
switch $method {
|
|
get {return [eval "get_$type $parms"]}
|
|
set {return [eval "set_$type $parms"]}
|
|
delete {eval "delete_$type $ptr; rename $ptr {}"}
|
|
}
|
|
}
|
|
# Create a procedure
|
|
uplevel "proc $ptr args {set ptr $ptr; set type $type;$code}"
|
|
return $ptr
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
Our script allows easy array access as follows :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
set a [Array double 100] ;# Create a double [100]
|
|
for {set i 0} {$i < 100} {incr i 1} { ;# Clear the array
|
|
$a set $i 0.0
|
|
}
|
|
$a set 3 3.1455 ;# Set an individual element
|
|
set b [$a get 10] ;# Retrieve an element
|
|
|
|
set ia [Array int 50] ;# Create an int[50]
|
|
for {set i 0} {$i < 50} {incr i 1} { ;# Clear it
|
|
$ia set $i 0
|
|
}
|
|
$ia set 3 7 ;# Set an individual element
|
|
set ib [$ia get 10] ;# Get an individual element
|
|
|
|
$a delete ;# Destroy a
|
|
$ia delete ;# Destroy ia
|
|
</pre></div>
|
|
|
|
<p>
|
|
The cool thing about this approach is that it makes a common interface
|
|
for two different types of arrays. In fact, if we were to add more C
|
|
datatypes to our wrapper file, the Tcl code would work with those as
|
|
well--without modification. If an unsupported datatype was requested,
|
|
the Tcl code would simply return with an error so there is very little
|
|
danger of blowing something up (although it is easily accomplished
|
|
with an out of bounds array access).
|
|
</p>
|
|
|
|
<H3><a name="Tcl_nn45">37.9.1 Proxy classes</a></H3>
|
|
|
|
|
|
<p>
|
|
A similar approach can be applied to proxy classes (also known as
|
|
shadow classes). The following
|
|
example is provided by Erik Bierwagen and Paul Saxe. To use it, run
|
|
SWIG with the <tt>-noobject</tt> option (which disables the builtin
|
|
object oriented interface). When running Tcl, simply source this
|
|
file. Now, objects can be used in a more or less natural fashion.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
# swig_c++.tcl
|
|
# Provides a simple object oriented interface using
|
|
# SWIG's low level interface.
|
|
#
|
|
|
|
proc new {objectType handle_r args} {
|
|
# Creates a new SWIG object of the given type,
|
|
# returning a handle in the variable "handle_r".
|
|
#
|
|
# Also creates a procedure for the object and a trace on
|
|
# the handle variable that deletes the object when the
|
|
# handle variable is overwritten or unset
|
|
upvar $handle_r handle
|
|
#
|
|
# Create the new object
|
|
#
|
|
eval set handle \[new_$objectType $args\]
|
|
#
|
|
# Set up the object procedure
|
|
#
|
|
proc $handle {cmd args} "eval ${objectType}_\$cmd $handle \$args"
|
|
#
|
|
# And the trace ...
|
|
#
|
|
uplevel trace variable $handle_r uw "{deleteObject $objectType $handle}"
|
|
#
|
|
# Return the handle so that 'new' can be used as an argument to a procedure
|
|
#
|
|
return $handle
|
|
}
|
|
|
|
proc deleteObject {objectType handle name element op} {
|
|
#
|
|
# Check that the object handle has a reasonable form
|
|
#
|
|
if {![regexp {_[0-9a-f]*_(.+)_p} $handle]} {
|
|
error "deleteObject: not a valid object handle: $handle"
|
|
}
|
|
#
|
|
# Remove the object procedure
|
|
#
|
|
catch {rename $handle {}}
|
|
#
|
|
# Delete the object
|
|
#
|
|
delete_$objectType $handle
|
|
}
|
|
|
|
proc delete {handle_r} {
|
|
#
|
|
# A synonym for unset that is more familiar to C++ programmers
|
|
#
|
|
uplevel unset $handle_r
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
To use this file, we simply source it and execute commands such as
|
|
"new" and "delete" to manipulate objects. For example :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
// list.i
|
|
%module List
|
|
%{
|
|
#include "list.h"
|
|
%}
|
|
|
|
// Very simple C++ example
|
|
|
|
class List {
|
|
public:
|
|
List(); // Create a new list
|
|
~List(); // Destroy a list
|
|
int search(char *value);
|
|
void insert(char *); // Insert a new item into the list
|
|
void remove(char *); // Remove item from list
|
|
char *get(int n); // Get the nth item in the list
|
|
int length; // The current length of the list
|
|
static void print(List *l); // Print out the contents of the list
|
|
};
|
|
</pre></div>
|
|
|
|
<p>
|
|
Now a Tcl script using the interface...
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
load ./list.so list ; # Load the module
|
|
source swig_c++.tcl ; # Source the object file
|
|
|
|
new List l
|
|
$l insert Dave
|
|
$l insert John
|
|
$l insert Guido
|
|
$l remove Dave
|
|
puts $l length_get
|
|
|
|
delete l
|
|
</pre></div>
|
|
|
|
<p>
|
|
The cool thing about this example is that it works with any C++ object
|
|
wrapped by SWIG and requires no special compilation. Proof that a
|
|
short, but clever Tcl script can be combined with SWIG to do many
|
|
interesting things.
|
|
</p>
|
|
|
|
<H2><a name="Tcl_nn46">37.10 Tcl/Tk Stubs</a></H2>
|
|
|
|
|
|
<p>
|
|
For background information about the Tcl Stubs feature, see
|
|
<a href="https://www.tcl.tk/doc/howto/stubs.html">https://www.tcl.tk/doc/howto/stubs.html</a>.
|
|
</p>
|
|
|
|
<p>
|
|
As of SWIG 1.3.10, the generated C/C++ wrapper will use the Tcl Stubs
|
|
feature if compiled with <tt>-DUSE_TCL_STUBS</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
As of SWIG 1.3.40, the generated C/C++ wrapper will use the Tk Stubs
|
|
feature if compiled with <tt>-DUSE_TK_STUBS</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
By default SWIG sets the minimum Tcl version to support to the 8.4
|
|
as that's the minimum Tcl version we aim to support (since SWIG 4.1.0; before
|
|
this SWIG set it to 8.1, which was the first Tcl version with the stubs
|
|
mechanism). This minimum version is passed to <tt>Tcl_InitStubs()</tt> and
|
|
<tt>Tk_InitStubs()</tt>. You can override with a specific version using
|
|
<tt>-DSWIG_TCL_STUBS_VERSION="8.5"</tt> or set it to the Tcl version being
|
|
compiled with using <tt>-DSWIG_TCL_STUBS_VERSION=TCL_VERSION</tt>.
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|