| <!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">36 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. SWIG currently requires |
| Tcl 8.0 or a later release. Earlier releases of SWIG supported Tcl 7.x, but |
| this is no longer supported. |
| </p> |
| |
| <H2><a name="Tcl_nn2">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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 its enough |
| to get you started. With a little practice, you'll be making lots of |
| Tcl extensions. |
| </p> |
| |
| <H2><a name="Tcl_nn14">36.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">36.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">36.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">36.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">36.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">36.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">36.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. 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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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">36.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 len, int *success); |
| </pre> |
| </div> |
| |
| <p> |
| To wrap such a function, simply use the <tt>OUTPUT</tt> rule above. For example: |
| </p> |
| |
| <div class="code"> |
| <pre> |
| %module example |
| %include "typemaps.i" |
| %apply int *OUTPUT { int *success }; |
| ... |
| int send_message(char *text, int *success); |
| </pre> |
| </div> |
| |
| <p> |
| When used in 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">36.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">36.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">36.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">36.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">36.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">36.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 ** { |
| if ($1) { |
| 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">36.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">36.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">36.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">36.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">36.8 Turning a SWIG module into a Tcl Package.</a></H2> |
| |
| |
| <p> |
| Tcl 7.4 introduced the idea of an extension package. By default, SWIG |
| generates all of the code necessary to create a package. To set the package version, |
| simply 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">36.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">36.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">36.10 Tcl/Tk Stubs</a></H2> |
| |
| |
| <p> |
| For background information about the Tcl Stubs feature, see |
| <a href="http://www.tcl.tk/doc/howto/stubs.html">http://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>. Also, you can override |
| the minimum version to support which is passed to <tt>Tcl_InitStubs()</tt> |
| and <tt>Tk_InitStubs()</tt> with <tt>-DSWIG_TCL_STUBS_VERSION="8.3"</tt> |
| or the version being compiled with using |
| <tt>-DSWIG_TCL_STUBS_VERSION=TCL_VERSION</tt>. |
| </p> |
| |
| </body> |
| </html> |