Table of ContentsSWIG-1.3 Documentation
Table of Contents
16 Using SWIG with ccache - ccache-swig(1) manpage 17 SWIG and Allegro Common Lisp 35 Extending SWIG to support new languages SWIG-1.3 Development DocumentationLast update : SWIG-1.3.40 (18 August 2009) SectionsThe SWIG documentation is being updated to reflect new SWIG features and enhancements. However, this update process is not quite finished–there is a lot of old SWIG-1.1 documentation and it is taking some time to update all of it. Please pardon our dust (or volunteer to help!). SWIG Core Documentation
Language Module DocumentationDeveloper DocumentationDocumentation that has not yet been updatedThis documentation has not been completely updated from SWIG-1.1, but most of the topics still apply to the current release. Make sure you read the SWIG Basics chapter before reading any of these chapters. Also, SWIG-1.3.10 features extensive changes to the implementation of typemaps. Make sure you read the Typemaps chapter above if you are using this feature.
1 Preface1.1 IntroductionSWIG (Simplified Wrapper and Interface Generator) is a software development tool for building scripting language interfaces to C and C++ programs. Originally developed in 1995, SWIG was first used by scientists in the Theoretical Physics Division at Los Alamos National Laboratory for building user interfaces to simulation codes running on the Connection Machine 5 supercomputer. In this environment, scientists needed to work with huge amounts of simulation data, complex hardware, and a constantly changing code base. The use of a scripting language interface provided a simple yet highly flexible foundation for solving these types of problems. SWIG simplifies development by largely automating the task of scripting language integration–allowing developers and users to focus on more important problems. Although SWIG was originally developed for scientific applications, it has since evolved into a general purpose tool that is used in a wide variety of applications–in fact almost anything where C/C++ programming is involved. 1.2 Special Introduction for Version 1.3Since SWIG was released in 1996, its user base and applicability has continued to grow. Although its rate of development has varied, an active development effort has continued to make improvements to the system. Today, nearly a dozen developers are working to create SWIG-2.0—a system that aims to provide wrapping support for nearly all of the ANSI C++ standard and approximately ten target languages including Guile, Java, Mzscheme, Ocaml, Perl, Pike, PHP, Python, Ruby, and Tcl. 1.3 SWIG VersionsFor several years, the most stable version of SWIG has been release 1.1p5. Starting with version 1.3, a new version numbering scheme has been adopted. Odd version numbers (1.3, 1.5, etc.) represent development versions of SWIG. Even version numbers (1.4, 1.6, etc.) represent stable releases. Currently, developers are working to create a stable SWIG-2.0 release. Don't let the development status of SWIG-1.3 scare you—it is much more stable (and capable) than SWIG-1.1p5. 1.4 SWIG resourcesThe official location of SWIG related material is http://www.swig.org This site contains the latest version of the software, users guide, and information regarding bugs, installation problems, and implementation tricks. You can also subscribe to the swig-user mailing list by visiting the page http://www.swig.org/mail.html The mailing list often discusses some of the more technical aspects of SWIG along with information about beta releases and future work. SVN access to the latest version of SWIG is also available. More information about this can be obtained at: http://www.swig.org/svn.html 1.5 PrerequisitesThis manual assumes that you know how to write C/C++ programs and that you have at least heard of scripting languages such as Tcl, Python, and Perl. A detailed knowledge of these scripting languages is not required although some familiarity won't hurt. No prior experience with building C extensions to these languages is required—after all, this is what SWIG does automatically. However, you should be reasonably familiar with the use of compilers, linkers, and makefiles since making scripting language extensions is somewhat more complicated than writing a normal C program. Recent SWIG releases have become significantly more capable in their C++ handling–especially support for advanced features like namespaces, overloaded operators, and templates. Whenever possible, this manual tries to cover the technicalities of this interface. However, this isn't meant to be a tutorial on C++ programming. For many of the gory details, you will almost certainly want to consult a good C++ reference. If you don't program in C++, you may just want to skip those parts of the manual. 1.6 Organization of this manualThe first few chapters of this manual describe SWIG in general and provide an overview of its capabilities. The remaining chapters are devoted to specific SWIG language modules and are self contained. Thus, if you are using SWIG to build Python interfaces, you can probably skip to that chapter and find almost everything you need to know. Caveat: we are currently working on a documentation rewrite and many of the older language module chapters are still somewhat out of date. 1.7 How to avoid reading the manualIf you hate reading manuals, glance at the “Introduction” which contains a few simple examples. These examples contain about 95% of everything you need to know to use SWIG. After that, simply use the language-specific chapters as a reference. The SWIG distribution also comes with a large directory of examples that illustrate different topics. 1.8 Backwards CompatibilityIf you are a previous user of SWIG, don't expect recent versions of SWIG to provide backwards compatibility. In fact, backwards compatibility issues may arise even between successive 1.3.x releases. Although these incompatibilities are regrettable, SWIG-1.3 is an active development project. The primary goal of this effort is to make SWIG better—a process that would simply be impossible if the developers are constantly bogged down with backwards compatibility issues. On a positive note, a few incompatibilities are a small price to pay for the large number of new features that have been added—namespaces, templates, smart pointers, overloaded methods, operators, and more. If you need to work with different versions of SWIG and backwards compatibility is an issue, you can use the SWIG_VERSION preprocessor symbol which holds the version of SWIG being executed. SWIG_VERSION is a hexadecimal integer such as 0x010311 (corresponding to SWIG-1.3.11). This can be used in an interface file to define different typemaps, take advantage of different features etc: #if SWIG_VERSION >= 0x010311 /* Use some fancy new feature */ #endif Note: The version symbol is not defined in the generated SWIG wrapper file. The SWIG preprocessor has defined SWIG_VERSION since SWIG-1.3.11. 1.9 CreditsSWIG is an unfunded project that would not be possible without the contributions of many people. Most recent SWIG development has been supported by Matthias Köppe, William Fulton, Lyle Johnson, Richard Palmer, Thien-Thi Nguyen, Jason Stewart, Loic Dachary, Masaki Fukushima, Luigi Ballabio, Sam Liddicott, Art Yerkes, Marcelo Matus, Harco de Hilster, John Lenz, and Surendra Singhi. Historically, the following people contributed to early versions of SWIG. Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann at Los Alamos National Laboratory were the first users. Patrick Tullmann at the University of Utah suggested the idea of automatic documentation generation. John Schmidt and Kurtis Bleeker at the University of Utah tested out the early versions. Chris Johnson supported SWIG's developed at the University of Utah. John Buckman, Larry Virden, and Tom Schwaller provided valuable input on the first releases and improving the portability of SWIG. David Fletcher and Gary Holt have provided a great deal of input on improving SWIG's Perl5 implementation. Kevin Butler contributed the first Windows NT port. 1.10 Bug reportsAlthough every attempt has been made to make SWIG bug-free, we are also trying to make feature improvements that may introduce bugs. To report a bug, either send mail to the SWIG developer list at the swig-devel mailing list or report a bug at the SWIG bug tracker. In your report, be as specific as possible, including (if applicable), error messages, tracebacks (if a core dump occurred), corresponding portions of the SWIG interface file used, and any important pieces of the SWIG generated wrapper code. We can only fix bugs if we know about them. 2 Introduction2.1 What is SWIG?SWIG is a software development tool that simplifies the task of interfacing different languages to C and C++ programs. In a nutshell, SWIG is a compiler that takes C declarations and creates the wrappers needed to access those declarations from other languages including including Perl, Python, Tcl, Ruby, Guile, and Java. SWIG normally requires no modifications to existing code and can often be used to build a usable interface in only a few minutes. Possible applications of SWIG include:
SWIG was originally designed to make it extremely easy for scientists and engineers to build extensible scientific software without having to get a degree in software engineering. Because of this, the use of SWIG tends to be somewhat informal and ad-hoc (e.g., SWIG does not require users to provide formal interface specifications as you would find in a dedicated IDL compiler). Although this style of development isn't appropriate for every project, it is particularly well suited to software development in the small; especially the research and development work that is commonly found in scientific and engineering projects. 2.2 Why use SWIG?As stated in the previous section, the primary purpose of SWIG is to simplify the task of integrating C/C++ with other programming languages. However, why would anyone want to do that? To answer that question, it is useful to list a few strengths of C/C++ programming:
Next, let's list a few problems with C/C++ programming
To address these limitations, many programmers have arrived at the conclusion that it is much easier to use different programming languages for different tasks. For instance, writing a graphical user interface may be significantly easier in a scripting language like Python or Tcl (consider the reasons why millions of programmers have used languages like Visual Basic if you need more proof). An interactive interpreter might also serve as a useful debugging and testing tool. Other languages like Java might greatly simplify the task of writing distributed computing software. The key point is that different programming languages offer different strengths and weaknesses. Moreover, it is extremely unlikely that any programming is ever going to be perfect. Therefore, by combining languages together, you can utilize the best features of each language and greatly simplify certain aspects of software development. From the standpoint of C/C++, a lot of people use SWIG because they want to break out of the traditional monolithic C programming model which usually results in programs that resemble this:
Instead of going down that route, incorporating C/C++ into a higher level language often results in a more modular design, less code, better flexibility, and increased programmer productivity. SWIG tries to make the problem of C/C++ integration as painless as possible. This allows you to focus on the underlying C program and using the high-level language interface, but not the tedious and complex chore of making the two languages talk to each other. At the same time, SWIG recognizes that all applications are different. Therefore, it provides a wide variety of customization features that let you change almost every aspect of the language bindings. This is the main reason why SWIG has such a large user manual . 2.3 A SWIG exampleThe best way to illustrate SWIG is with a simple example. Consider the following C code: /* File : example.c */ double My_variable = 3.0; /* Compute factorial of n */ int fact(int n) { if (n <= 1) return 1; else return n*fact(n-1); } /* Compute n mod m */ int my_mod(int n, int m) { return(n % m); }
Suppose that you wanted to access these functions and the global variable 2.3.1 SWIG interface file/* File : example.i */ %module example %{ /* Put headers and other declarations here */ extern double My_variable; extern int fact(int); extern int my_mod(int n, int m); %} extern double My_variable; extern int fact(int); extern int my_mod(int n, int m);
The interface file contains ANSI C function prototypes and variable declarations. The 2.3.2 The swig command
SWIG is invoked using the unix > swig -tcl example.i unix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include unix > gcc -shared example.o example_wrap.o -o example.so unix > tclsh % load ./example.so % fact 4 24 % my_mod 23 7 2 % expr $My_variable + 4.5 7.5 %
The 2.3.3 Building a Perl5 moduleNow, let's turn these functions into a Perl5 module. Without making any changes type the following (shown for Solaris): unix > swig -perl5 example.i unix > gcc -c example.c example_wrap.c \ -I/usr/local/lib/perl5/sun4-solaris/5.003/CORE unix > ld -G example.o example_wrap.o -o example.so # This is for Solaris unix > perl5.003 use example; print example::fact(4), "\n"; print example::my_mod(23,7), "\n"; print $example::My_variable + 4.5, "\n"; <ctrl-d> 24 2 7.5 unix > 2.3.4 Building a Python moduleFinally, let's build a module for Python (shown for Irix). unix > swig -python example.i unix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include/python2.0 unix > gcc -shared example.o example_wrap.o -o _example.so unix > python Python 2.0 (#6, Feb 21 2001, 13:29:45) [GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2 Type "copyright", "credits" or "license" for more information. >>> import example >>> example.fact(4) 24 >>> example.my_mod(23,7) 2 >>> example.cvar.My_variable + 4.5 7.5 2.3.5 ShortcutsTo the truly lazy programmer, one may wonder why we needed the extra interface file at all. As it turns out, you can often do without it. For example, you could also build a Perl5 module by just running SWIG on the C header file and specifying a module name as follows unix > swig -perl5 -module example example.h unix > gcc -c example.c example_wrap.c \ -I/usr/local/lib/perl5/sun4-solaris/5.003/CORE unix > ld -G example.o example_wrap.o -o example.so unix > perl5.003 use example; print example::fact(4), "\n"; print example::my_mod(23,7), "\n"; print $example::My_variable + 4.5, "\n"; <ctrl-d> 24 2 7.5 2.4 Supported C/C++ language featuresA primary goal of the SWIG project is to make the language binding process extremely easy. Although a few simple examples have been shown, SWIG is quite capable in supporting most of C++. Some of the major features include:
Currently, the only major C++ feature not supported is nested classes–a limitation that will be removed in a future release. It is important to stress that SWIG is not a simplistic C++ lexing tool like several apparently similar wrapper generation tools. SWIG not only parses C++, it implements the full C++ type system and it is able to understand C++ semantics. SWIG generates its wrappers with full knowledge of this information. As a result, you will find SWIG to be just as capable of dealing with nasty corner cases as it is in wrapping simple C++ code. In fact, SWIG is able handle C++ code that stresses the very limits of many C++ compilers. 2.5 Non-intrusive interface buildingWhen used as intended, SWIG requires minimal (if any) modification to existing C or C++ code. This makes SWIG extremely easy to use with existing packages and promotes software reuse and modularity. By making the C/C++ code independent of the high level interface, you can change the interface and reuse the code in other applications. It is also possible to support different types of interfaces depending on the application. 2.6 Incorporating SWIG into a build systemSWIG is a command line tool and as such can be incorporated into any build system that supports invoking external tools/compilers. SWIG is most commonly invoked from within a Makefile, but is also known to be invoked from from popular IDEs such as Microsoft Visual Studio.
If you are using the GNU Autotools (Autoconf/ Automake / Libtool) to configure SWIG use in your project, the SWIG Autoconf macros can be used. The primary macro is There is growing support for SWIG in some build tools, for example CMake is a cross-platform, open-source build manager with built in support for SWIG. CMake can detect the SWIG executable and many of the target language libraries for linking against. CMake knows how to build shared libraries and loadable modules on many different operating systems. This allows easy cross platform SWIG development. It also can generate the custom commands necessary for driving SWIG from IDE's and makefiles. All of this can be done from a single cross platform input file. The following example is a CMake input file for creating a python wrapper for the SWIG interface file, example.i: # This is a CMake example for Python FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(PythonLibs) INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(CMAKE_SWIG_FLAGS "") SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall") SWIG_ADD_MODULE(example python example.i example.cxx) SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES}) The above example will generate native build files such as makefiles, nmake files and Visual Studio projects which will invoke SWIG and compile the generated C++ files into _example.so (UNIX) or _example.pyd (Windows). For other target languages on Windows a dll, instead of a .pyd file, is usually generated. 2.7 Hands off code generationSWIG is designed to produce working code that needs no hand-modification (in fact, if you look at the output, you probably won't want to modify it). You should think of your target language interface being defined entirely by the input to SWIG, not the resulting output file. While this approach may limit flexibility for hard-core hackers, it allows others to forget about the low-level implementation details. 2.8 SWIG and freedomNo, this isn't a special section on the sorry state of world politics. However, it may be useful to know that SWIG was written with a certain “philosophy” about programming—namely that programmers are smart and that tools should just stay out of their way. Because of that, you will find that SWIG is extremely permissive in what it lets you get away with. In fact, you can use SWIG to go well beyond “shooting yourself in the foot” if dangerous programming is your goal. On the other hand, this kind of freedom may be exactly what is needed to work with complicated and unusual C/C++ applications. Ironically, the freedom that SWIG provides is countered by an extremely conservative approach to code generation. At it's core, SWIG tries to distill even the most advanced C++ code down to a small well-defined set of interface building techniques based on ANSI C programming. Because of this, you will find that SWIG interfaces can be easily compiled by virtually every C/C++ compiler and that they can be used on any platform. Again, this is an important part of staying out of the programmer's way—-the last thing any developer wants to do is to spend their time debugging the output of a tool that relies on non-portable or unreliable programming features. 3 Getting started on WindowsThis chapter describes SWIG usage on Microsoft Windows. Installing SWIG and running the examples is covered as well as building the SWIG executable. Usage within the Unix like environments MinGW and Cygwin is also detailed. 3.1 Installation on WindowsSWIG does not come with the usual Windows type installation program, however it is quite easy to get started. The main steps are:
3.1.1 Windows ExecutableThe swigwin distribution contains the SWIG Windows executable, swig.exe, which will run on 32 bit versions of Windows, ie Windows 95/98/ME/NT/2000/XP. If you want to build your own swig.exe have a look at Building swig.exe on Windows. 3.2 SWIG Windows ExamplesUsing Microsoft Visual C++ is the most common approach to compiling and linking SWIG's output. The Examples directory has a few Visual C++ project files (.dsp files). These were produced by Visual C++ 6, although they should also work in Visual C++ 5. Later versions of Visual Studio should also be able to open and convert these project files. The C# examples come with .NET 2003 solution (.sln) and project files instead of Visual C++ 6 project files. The project files have been set up to execute SWIG in a custom build rule for the SWIG interface (.i) file. Alternatively run the examples using Cygwin. More information on each of the examples is available with the examples distributed with SWIG (Examples/index.html). 3.2.1 Instructions for using the Examples with Visual StudioEnsure the SWIG executable is as supplied in the SWIG root directory in order for the examples to work. Most languages require some environment variables to be set before running Visual C++. Note that Visual C++ must be re-started to pick up any changes in environment variables. Open up an example .dsp file, Visual C++ will create a workspace for you (.dsw file). Ensure the Release build is selected then do a Rebuild All from the Build menu. The required environment variables are displayed with their current values. The list of required environment variables for each module language is also listed below. They are usually set from the Control Panel and System properties, but this depends on which flavour of Windows you are running. If you don't want to use environment variables then change all occurrences of the environment variables in the .dsp files with hard coded values. If you are interested in how the project files are set up there is explanatory information in some of the language module's documentation. 3.2.1.1 C#The C# examples do not require any environment variables to be set as a C# project file is included. Just open up the .sln solution file in Visual Studio .NET 2003 or later, select Release Build, and do a Rebuild All from the Build menu. The accompanying C# and C++ project files are automatically used by the solution file. 3.2.1.2 Java
Example using JDK1.3: 3.2.1.3 Perl
Example using nsPerl 5.004_04:
3.2.1.4 Python
Example using Python 2.1.1: 3.2.1.5 TCL
Example using ActiveTcl 8.3.3.3 3.2.1.6 R
Example using R 2.5.1: 3.2.1.7 Ruby
Example using Ruby 1.6.4: 3.2.2 Instructions for using the Examples with other compilersIf you do not have access to Visual C++ you will have to set up project files / Makefiles for your chosen compiler. There is a section in each of the language modules detailing what needs setting up using Visual C++ which may be of some guidance. Alternatively you may want to use Cygwin as described in the following section. 3.3 SWIG on Cygwin and MinGWSWIG can also be compiled and run using Cygwin or MinGW which provides a Unix like front end to Windows and comes free with gcc, an ANSI C/C++ compiler. However, this is not a recommended approach as the prebuilt executable is supplied. 3.3.1 Building swig.exe on WindowsIf you want to replicate the build of swig.exe that comes with the download, follow the MinGW instructions below. This is not necessary to use the supplied swig.exe. This information is provided for those that want to modify the SWIG source code in a Windows environment. Normally this is not needed, so most people will want to ignore this section. 3.3.1.1 Building swig.exe using MinGW and MSYSThe short abbreviated instructions follow…
The step by step instructions to download and install MinGW and MSYS, then download and build the latest version of SWIG from SVN follow… Note that the instructions for obtaining SWIG from SVN are also online at SWIG SVN. Pitfall note: Execute the steps in the order shown and don't use spaces in path names. In fact it is best to use the default installation directories.
tar -jxf msys-automake-1.8.2.tar.bz2 tar -jxf msys-autoconf-2.59.tar.bz2 tar -zxf bison-2.0-MSYS.tar.gz
cd /usr/src svn co https://swig.svn.sourceforge.net/svnroot/swig/trunk swig Pitfall note: If you want to check out SWIG to a different folder to the proposed /usr/src/swig, do not use MSYS emulated windows drive letters, because the autotools will fail miserably on those.
./autogen.sh ./configure make 3.3.1.2 Building swig.exe using Cygwin
Note that SWIG can also be built using Cygwin. However, SWIG will then require the Cygwin DLL when executing. Follow the Unix instructions in the README file in the SWIG root directory. Note that the Cygwin environment will also allow one to regenerate the autotool generated files which are supplied with the release distribution. These files are generated using the 3.3.1.3 Building swig.exe alternativesIf you don't want to install Cygwin or MinGW, use a different compiler to build SWIG. For example, all the source code files can be added to a Visual C++ project file in order to build swig.exe from the Visual C++ IDE. 3.3.2 Running the examples on Windows using CygwinThe examples and test-suite work as successfully on Cygwin as on any other Unix operating system. The modules which are known to work are Python, Tcl, Perl, Ruby, Java and C#. Follow the Unix instructions in the README file in the SWIG root directory to build the examples. 3.4 Microsoft extensions and other Windows quirks
A common problem when using SWIG on Windows are the Microsoft function calling conventions which are not in the C++ standard. SWIG parses ISO C/C++ so cannot deal with proprietary conventions such as %include <windows.i> __declspec(dllexport) ULONG __stdcall foo(DWORD, __int32); 4 Scripting LanguagesThis chapter provides a brief overview of scripting language extension programming and the mechanisms by which scripting language interpreters access C and C++ code. 4.1 The two language view of the worldWhen a scripting language is used to control a C program, the resulting system tends to look as follows: In this programming model, the scripting language interpreter is used for high level control whereas the underlying functionality of the C/C++ program is accessed through special scripting language “commands.” If you have ever tried to write your own simple command interpreter, you might view the scripting language approach to be a highly advanced implementation of that. Likewise, If you have ever used a package such as MATLAB or IDL, it is a very similar model–the interpreter executes user commands and scripts. However, most of the underlying functionality is written in a low-level language like C or Fortran. The two-language model of computing is extremely powerful because it exploits the strengths of each language. C/C++ can be used for maximal performance and complicated systems programming tasks. Scripting languages can be used for rapid prototyping, interactive debugging, scripting, and access to high-level data structures such associative arrays. 4.2 How does a scripting language talk to C?Scripting languages are built around a parser that knows how to execute commands and scripts. Within this parser, there is a mechanism for executing commands and accessing variables. Normally, this is used to implement the builtin features of the language. However, by extending the interpreter, it is usually possible to add new commands and variables. To do this, most languages define a special API for adding new commands. Furthermore, a special foreign function interface defines how these new commands are supposed to hook into the interpreter. Typically, when you add a new command to a scripting interpreter you need to do two things; first you need to write a special “wrapper” function that serves as the glue between the interpreter and the underlying C function. Then you need to give the interpreter information about the wrapper by providing details about the name of the function, arguments, and so forth. The next few sections illustrate the process. 4.2.1 Wrapper functionsSuppose you have an ordinary C function like this : int fact(int n) { if (n <= 1) return 1; else return n*fact(n-1); } In order to access this function from a scripting language, it is necessary to write a special “wrapper” function that serves as the glue between the scripting language and the underlying C function. A wrapper function must do three things :
As an example, the Tcl wrapper function for the int wrap_fact(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { int result; int arg0; if (argc != 2) { interp->result = "wrong # args"; return TCL_ERROR; } arg0 = atoi(argv[1]); result = fact(arg0); sprintf(interp->result,"%d", result); return TCL_OK; } Once you have created a wrapper function, the final step is to tell the scripting language about the new function. This is usually done in an initialization function called by the language when the module is loaded. For example, adding the above function to the Tcl interpreter requires code like the following : int Wrap_Init(Tcl_Interp *interp) { Tcl_CreateCommand(interp, "fact", wrap_fact, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); return TCL_OK; }
When executed, Tcl will now have a new command called “ Although the process of adding a new function to Tcl has been illustrated, the procedure is almost identical for Perl and Python. Both require special wrappers to be written and both need additional initialization code. Only the specific details are different. 4.2.2 Variable linkingVariable linking refers to the problem of mapping a C/C++ global variable to a variable in the scripting language interpreter. For example, suppose you had the following variable: double Foo = 3.5; It might be nice to access it from a script as follows (shown for Perl): $a = $Foo * 2.3; # Evaluation $Foo = $a + 2.0; # Assignment To provide such access, variables are commonly manipulated using a pair of get/set functions. For example, whenever the value of a variable is read, a “get” function is invoked. Similarly, whenever the value of a variable is changed, a “set” function is called.
In many languages, calls to the get/set functions can be attached to evaluation and assignment operators. Therefore, evaluating a variable such as 4.2.3 ConstantsIn many cases, a C program or library may define a large collection of constants. For example: #define RED 0xff0000 #define BLUE 0x0000ff #define GREEN 0x00ff00
To make constants available, their values can be stored in scripting language variables such as 4.2.4 Structures and classesAlthough scripting languages have no trouble accessing simple functions and variables, accessing C/C++ structures and classes present a different problem. This is because the implementation of structures is largely related to the problem of data representation and layout. Furthermore, certain language features are difficult to map to an interpreter. For instance, what does C++ inheritance mean in a Perl interface? The most straightforward technique for handling structures is to implement a collection of accessor functions that hide the underlying representation of a structure. For example, struct Vector { Vector(); ~Vector(); double x,y,z; }; can be transformed into the following set of functions : Vector *new_Vector(); void delete_Vector(Vector *v); double Vector_x_get(Vector *v); double Vector_y_get(Vector *v); double Vector_z_get(Vector *v); void Vector_x_set(Vector *v, double x); void Vector_y_set(Vector *v, double y); void Vector_z_set(Vector *v, double z); Now, from an interpreter these function might be used as follows: % set v [new_Vector] % Vector_x_set $v 3.5 % Vector_y_get $v % delete_Vector $v % ...
Since accessor functions provide a mechanism for accessing the internals of an object, the interpreter does not need to know anything about the actual representation of a 4.2.5 Proxy classesIn certain cases, it is possible to use the low-level accessor functions to create a proxy class, also known as a shadow class. A proxy class is a special kind of object that gets created in a scripting language to access a C/C++ class (or struct) in a way that looks like the original structure (that is, it proxies the real C++ class). For example, if you have the following C definition : class Vector { public: Vector(); ~Vector(); double x,y,z; }; A proxy classing mechanism would allow you to access the structure in a more natural manner from the interpreter. For example, in Python, you might want to do this: >>> v = Vector() >>> v.x = 3 >>> v.y = 4 >>> v.z = -13 >>> ... >>> del v Similarly, in Perl5 you may want the interface to work like this: $v = new Vector; $v->{x} = 3; $v->{y} = 4; $v->{z} = -13; Finally, in Tcl : Vector v v configure -x 3 -y 4 -z 13 When proxy classes are used, two objects are at really work–one in the scripting language, and an underlying C/C++ object. Operations affect both objects equally and for all practical purposes, it appears as if you are simply manipulating a C/C++ object. 4.3 Building scripting language extensionsThe final step in using a scripting language with your C/C++ application is adding your extensions to the scripting language itself. There are two primary approaches for doing this. The preferred technique is to build a dynamically loadable extension in the form a shared library. Alternatively, you can recompile the scripting language interpreter with your extensions added to it. 4.3.1 Shared libraries and dynamic loadingTo create a shared library or DLL, you often need to look at the manual pages for your compiler and linker. However, the procedure for a few common machines is shown below: # Build a shared library for Solaris gcc -c example.c example_wrap.c -I/usr/local/include ld -G example.o example_wrap.o -o example.so # Build a shared library for Linux gcc -fpic -c example.c example_wrap.c -I/usr/local/include gcc -shared example.o example_wrap.o -o example.so # Build a shared library for Irix gcc -c example.c example_wrap.c -I/usr/local/include ld -shared example.o example_wrap.o -o example.so To use your shared library, you simply use the corresponding command in the scripting language (load, import, use, etc…). This will import your module and allow you to start using it. For example: % load ./example.so % fact 4 24 % When working with C++ codes, the process of building shared libraries may be more complicated–primarily due to the fact that C++ modules may need additional code in order to operate correctly. On many machines, you can build a shared C++ module by following the above procedures, but changing the link line to the following : c++ -shared example.o example_wrap.o -o example.so 4.3.2 Linking with shared librariesWhen building extensions as shared libraries, it is not uncommon for your extension to rely upon other shared libraries on your machine. In order for the extension to work, it needs to be able to find all of these libraries at run-time. Otherwise, you may get an error such as the following : >>> import graph Traceback (innermost last): File "<stdin>", line 1, in ? File "/home/sci/data1/beazley/graph/graph.py", line 2, in ? import graphc ImportError: 1101:/home/sci/data1/beazley/bin/python: rld: Fatal Error: cannot successfully map soname 'libgraph.so' under any of the filenames /usr/lib/libgraph.so:/ lib/libgraph.so:/lib/cmplrs/cc/libgraph.so:/usr/lib/cmplrs/cc/libgraph.so: >>>
What this error means is that the extension module created by SWIG depends upon a shared library called “
4.3.3 Static linkingWith static linking, you rebuild the scripting language interpreter with extensions. The process usually involves compiling a short main program that adds your customized commands to the language and starts the interpreter. You then link your program with a library to produce a new scripting language executable. Although static linking is supported on all platforms, this is not the preferred technique for building scripting language extensions. In fact, there are very few practical reasons for doing this–consider using shared libraries instead. 5 SWIG BasicsThis chapter describes the basic operation of SWIG, the structure of its input files, and how it handles standard ANSI C declarations. C++ support is described in the next chapter. However, C++ programmers should still read this chapter to understand the basics. Specific details about each target language are described in later chapters. 5.1 Running SWIG
To run SWIG, use the swig [ options ] filename
where -allegrocl Generate ALLEGROCL wrappers -chicken Generate CHICKEN wrappers -clisp Generate CLISP wrappers -cffi Generate CFFI wrappers -csharp Generate C# wrappers -guile Generate Guile wrappers -java Generate Java wrappers -lua Generate Lua wrappers -modula3 Generate Modula 3 wrappers -mzscheme Generate Mzscheme wrappers -ocaml Generate Ocaml wrappers -perl Generate Perl wrappers -php Generate PHP wrappers -pike Generate Pike wrappers -python Generate Python wrappers -r Generate R (aka GNU S) wrappers -ruby Generate Ruby wrappers -sexp Generate Lisp S-Expressions wrappers -tcl Generate Tcl wrappers -uffi Generate Common Lisp / UFFI wrappers -xml Generate XML wrappers -c++ Enable C++ parsing -Dsymbol Define a preprocessor symbol -Fstandard Display error/warning messages in commonly used format -Fmicrosoft Display error/warning messages in Microsoft format -help Display all options -Idir Add a directory to the file include path -lfile Include a SWIG library file. -module name Set the name of the SWIG module -o outfile Name of output file -outcurrentdir Set default output dir to current dir instead of input file's path -outdir dir Set language specific files output directory -swiglib Show location of SWIG library -version Show SWIG version number 5.1.1 Input format
As input, SWIG expects a file containing ANSI C/C++ declarations and special SWIG directives. More often than not, this is a special SWIG interface file which is usually denoted with a special The most common format of a SWIG interface is as follows: %module mymodule %{ #include "myheader.h" %} // Now list ANSI C/C++ declarations int foo; int bar(int x); ...
The module name is supplied using the special
Everything in the 5.1.2 SWIG Output
The output of SWIG is a C/C++ file that contains all of the wrapper code needed to build an extension module. SWIG may generate some additional files depending on the target language. By default, an input file with the name $ swig -c++ -python -o example_wrap.cpp example.i The C/C++ output file created by SWIG often contains everything that is needed to construct a extension module for the target scripting language. SWIG is not a stub compiler nor is it usually necessary to edit the output file (and if you look at the output, you probably won't want to). To build the final extension module, the SWIG output file is compiled and linked with the rest of your C/C++ program to create a shared library.
Many target languages will also generate proxy class files in the target language. The default output directory for these language specific files is the same directory as the generated C/C++ file. This can be modified using the $ swig -c++ -python -outdir pyfiles -o cppfiles/example_wrap.cpp example.i
If the directories cppfiles/example_wrap.cpp pyfiles/example.py
If the 5.1.3 CommentsC and C++ style comments may appear anywhere in interface files. In previous versions of SWIG, comments were used to generate documentation files. However, this feature is currently under repair and will reappear in a later SWIG release. 5.1.4 C Preprocessor
Like C, SWIG preprocesses all input files through an enhanced version of the C preprocessor. All standard preprocessor features are supported including file inclusion, conditional compilation and macros. However,
It should also be noted that the SWIG preprocessor skips all text enclosed inside a 5.1.5 SWIG Directives
Most of SWIG's operation is controlled by special directives that are always preceded by a “ Since SWIG directives are not legal C syntax, it is generally not possible to include them in header files. However, SWIG directives can be included in C header files using conditional compilation like this: /* header.h --- Some header file */ /* SWIG directives -- only seen if SWIG is running */ #ifdef SWIG %module foo #endif
5.1.6 Parser LimitationsAlthough SWIG can parse most C/C++ declarations, it does not provide a complete C/C++ parser implementation. Most of these limitations pertain to very complicated type declarations and certain advanced C++ features. Specifically, the following features are not currently supported:
const int extern Number; /* Extra declarator grouping */ Matrix (foo); // A global variable /* Extra declarator grouping in parameters */ void bar(Spam (Grok)(Doh)); In practice, few (if any) C programmers actually write code like this since this style is never featured in programming books. However, if you're feeling particularly obfuscated, you can certainly break SWIG (although why would you want to?).
int foo::bar(int) { ... whatever ... }
In the event of a parsing error, conditional compilation can be used to skip offending code. For example: #ifndef SWIG ... some bad declarations ... #endif Alternatively, you can just delete the offending code from the interface file. One of the reasons why SWIG does not provide a full C++ parser implementation is that it has been designed to work with incomplete specifications and to be very permissive in its handling of C/C++ datatypes (e.g., SWIG can generate interfaces even when there are missing class declarations or opaque datatypes). Unfortunately, this approach makes it extremely difficult to implement certain parts of a C/C++ parser as most compilers use type information to assist in the parsing of more complex declarations (for the truly curious, the primary complication in the implementation is that the SWIG parser does not utilize a separate typedef-name terminal symbol as described on p. 234 of K&R). 5.2 Wrapping Simple C DeclarationsSWIG wraps simple C declarations by creating an interface that closely matches the way in which the declarations would be used in a C program. For example, consider the following interface file: %module example %inline %{ extern double sin(double x); extern int strcmp(const char *, const char *); extern int Foo; %} #define STATUS 50 #define VERSION "1.1"
In this file, there are two functions % sin 3 5.2335956 % strcmp Dave Mike -1 % puts $Foo 42 % puts $STATUS 50 % puts $VERSION 1.1 Or in Python: >>> example.sin(3) 5.2335956 >>> example.strcmp('Dave','Mike') -1 >>> print example.cvar.Foo 42 >>> print example.STATUS 50 >>> print example.VERSION 1.1 Whenever possible, SWIG creates an interface that closely matches the underlying C/C++ code. However, due to subtle differences between languages, run-time environments, and semantics, it is not always possible to do so. The next few sections describes various aspects of this mapping. 5.2.1 Basic Type HandlingIn order to build an interface, SWIG has to convert C/C++ datatypes to equivalent types in the target language. Generally, scripting languages provide a more limited set of primitive types than C. Therefore, this conversion process involves a certain amount of type coercion.
Most scripting languages provide a single integer type that is implemented using the int short long unsigned signed unsigned short unsigned long unsigned char signed char bool When an integral value is converted from C, a cast is used to convert it to the representation in the target language. Thus, a 16 bit short in C may be promoted to a 32 bit integer. When integers are converted in the other direction, the value is cast back into the original C type. If the value is too large to fit, it is silently truncated.
The
Some care is required when working with large integer values. Most scripting languages use 32-bit integers so mapping a 64-bit long integer may lead to truncation errors. Similar problems may arise with 32 bit unsigned integers (which may appear as large negative numbers). As a rule of thumb, the
Although the SWIG parser supports the SWIG recognizes the following floating point types : float double
Floating point numbers are mapped to and from the natural representation of floats in the target language. This is almost always a C
The
The
At this time, SWIG provides limited support for Unicode and wide-character strings (the C 5.2.2 Global VariablesWhenever possible, SWIG maps C/C++ global variables into scripting language variables. For example, %module example double foo; results in a scripting language variable like this: # Tcl set foo [3.5] ;# Set foo to 3.5 puts $foo ;# Print the value of foo # Python cvar.foo = 3.5 # Set foo to 3.5 print cvar.foo # Print value of foo # Perl $foo = 3.5; # Set foo to 3.5 print $foo,"\n"; # Print value of foo # Ruby Module.foo = 3.5 # Set foo to 3.5 print Module.foo, "\n" # Print value of foo
Whenever the scripting language variable is used, the underlying C global variable is accessed. Although SWIG makes every attempt to make global variables work like scripting language variables, it is not always possible to do so. For instance, in Python, all global variables must be accessed through a special variable object known as
Finally, if a global variable has been declared as 5.2.3 Constants
Constants can be created using #define I_CONST 5 // An integer constant #define PI 3.14159 // A Floating point constant #define S_CONST "hello world" // A string constant #define NEWLINE '\n' // Character constant enum boolean {NO=0, YES=1}; enum months {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}; %constant double BLAH = 42.37; #define PI_4 PI/4 #define FLAGS 0x04 | 0x08 | 0x40
In #define EXTERN extern EXTERN void foo();
In this case, you probably don't want to create a constant called #define PI_4 PI/4
defines a constant because #define F_CONST (double) 5 // A floating pointer constant with cast The use of constant expressions is allowed, but SWIG does not evaluate them. Rather, it passes them through to the output file and lets the C compiler perform the final evaluation (SWIG does perform a limited form of type-checking however).
For enumerations, it is critical that the original enum definition be included somewhere in the interface file (either in a header file or in the
The 5.2.4 A brief word about const
A common confusion with C programming is the semantic meaning of the
Starting with SWIG-1.3, all variable declarations, regardless of any use of
Here are some examples of const char a; // A constant character char const b; // A constant character (the same) char *const c; // A constant pointer to a character const char *const d; // A constant pointer to a constant character
Here is an example of a declaration that is not const char *e; // A pointer to a constant character. The pointer // may be modified.
In this case, the pointer
Compatibility Note: One reason for changing SWIG to handle %constant double PI = 3.14159; or #ifdef SWIG #define const %constant #endif const double foo = 3.4; const double bar = 23.4; const int spam = 42; #ifdef SWIG #undef const #endif ... 5.2.5 A cautionary tale of char *
Before going any further, there is one bit of caution involving The primary source of problems are functions that might modify string data in place. A classic example would be a function like this: char *strcat(char *s, const char *t)
Although SWIG will certainly generate a wrapper for this, its behavior will be undefined. In fact, it will probably cause your application to crash with a segmentation fault or other memory related problem. This is because
The bottom line: don't rely on 5.3 Pointers and complex objectsMost C programs manipulate arrays, structures, and other types of objects. This section discusses the handling of these datatypes. 5.3.1 Simple pointersPointers to primitive C datatypes such as int * double *** char ** are fully supported by SWIG. Rather than trying to convert the data being pointed to into a scripting representation, SWIG simply encodes the pointer itself into a representation that contains the actual value of the pointer and a type-tag. Thus, the SWIG representation of the above pointers (in Tcl), might look like this: _10081012_p_int _1008e124_ppp_double _f8ac_pp_char A NULL pointer is represented by the string “NULL” or the value 0 encoded with type information. All pointers are treated as opaque objects by SWIG. Thus, a pointer may be returned by a function and passed around to other C functions as needed. For all practical purposes, the scripting language interface works in exactly the same way as you would use the pointer in a C program. The only difference is that there is no mechanism for dereferencing the pointer since this would require the target language to understand the memory layout of the underlying object.
The scripting language representation of a pointer value should never be manipulated directly. Even though the values shown look like hexadecimal addresses, the numbers used may differ from the actual machine address (e.g., on little-endian machines, the digits may appear in reverse order). Furthermore, SWIG does not normally map pointers into high-level objects such as associative arrays or lists (for example, converting an
5.3.2 Run time pointer type checkingBy allowing pointers to be manipulated from a scripting language, extension modules effectively bypass compile-time type checking in the C/C++ compiler. To prevent errors, a type signature is encoded into all pointer values and is used to perform run-time type checking. This type-checking process is an integral part of SWIG and can not be disabled or modified without using typemaps (described in later chapters).
Like C, 5.3.3 Derived types, structs, and classesFor everything else (structs, classes, arrays, etc…) SWIG applies a very simple rule : Everything else is a pointer In other words, SWIG manipulates everything else by reference. This model makes sense because most C/C++ programs make heavy use of pointers and SWIG can use the type-checked pointer mechanism already present for handling pointers to basic datatypes. Although this probably sounds complicated, it's really quite simple. Suppose you have an interface file like this : %module fileio FILE *fopen(char *, char *); int fclose(FILE *); unsigned fread(void *ptr, unsigned size, unsigned nobj, FILE *); unsigned fwrite(void *ptr, unsigned size, unsigned nobj, FILE *); void *malloc(int nbytes); void free(void *);
In this file, SWIG doesn't know what a # Copy a file def filecopy(source,target): f1 = fopen(source,"r") f2 = fopen(target,"w") buffer = malloc(8192) nbytes = fread(buffer,8192,1,f1) while (nbytes > 0): fwrite(buffer,8192,1,f2) nbytes = fread(buffer,8192,1,f1) free(buffer)
In this case 5.3.4 Undefined datatypesWhen SWIG encounters an undeclared datatype, it automatically assumes that it is a structure or class. For example, suppose the following function appeared in a SWIG input file: void matrix_multiply(Matrix *a, Matrix *b, Matrix *c);
SWIG has no idea what a “
Unlike C or C++, SWIG does not actually care whether An important detail to mention is that SWIG will gladly generate wrappers for an interface when there are unspecified type names. However, all unspecified types are internally handled as pointers to structures or classes! For example, consider the following declaration: void foo(size_t num);
If foo(40); TypeError: expected a _p_size_t.
The only way to fix this problem is to make sure you properly declare type names using 5.3.5 Typedef
Like C, typedef unsigned int size_t;
%{ /* Include in the generated wrapper file */ typedef unsigned int size_t; %} /* Tell SWIG about it */ typedef unsigned int size_t; or %inline %{ typedef unsigned int size_t; %} In certain cases, you might be able to include other header files to collect type information. For example: %module example %import "sys/types.h" In this case, you might run SWIG as follows: $ swig -I/usr/include -includeall example.i It should be noted that your mileage will vary greatly here. System headers are notoriously complicated and may rely upon a variety of non-standard C coding extensions (e.g., such as special directives to GCC). Unless you exactly specify the right include directories and preprocessor symbols, this may not work correctly (you will have to experiment).
SWIG tracks void foo(unsigned int *ptr);
The corresponding wrapper function will accept arguments of type 5.4 Other PracticalitiesSo far, this chapter has presented almost everything you need to know to use SWIG for simple interfaces. However, some C programs use idioms that are somewhat more difficult to map to a scripting language interface. This section describes some of these issues. 5.4.1 Passing structures by valueSometimes a C function takes structure parameters that are passed by value. For example, consider the following function: double dot_product(Vector a, Vector b); To deal with this, SWIG transforms the function to use pointers by creating a wrapper equivalent to the following: double wrap_dot_product(Vector *a, Vector *b) { Vector x = *a; Vector y = *b; return dot_product(x,y); }
In the target language, the 5.4.2 Return by valueC functions that return structures or classes datatypes by value are more difficult to handle. Consider the following function: Vector cross_product(Vector v1, Vector v2);
This function wants to return Vector *wrap_cross_product(Vector *v1, Vector *v2) { Vector x = *v1; Vector y = *v2; Vector *result; result = (Vector *) malloc(sizeof(Vector)); *(result) = cross(x,y); return result; }
or if SWIG was run with the Vector *wrap_cross(Vector *v1, Vector *v2) { Vector x = *v1; Vector y = *v2; Vector *result = new Vector(cross(x,y)); // Uses default copy constructor return result; } In both cases, SWIG allocates a new object and returns a reference to it. It is up to the user to delete the returned object when it is no longer in use. Clearly, this will leak memory if you are unaware of the implicit memory allocation and don't take steps to free the result. That said, it should be noted that some language modules can now automatically track newly created objects and reclaim memory for you. Consult the documentation for each language module for more details.
It should also be noted that the handling of pass/return by value in C++ has some special cases. For example, the above code fragments don't work correctly if 5.4.3 Linking to structure variablesWhen global variables or class members involving structures are encountered, SWIG handles them as pointers. For example, a global variable like this Vector unit_i; gets mapped to an underlying pair of set/get functions like this : Vector *unit_i_get() { return &unit_i; } void unit_i_set(Vector *value) { unit_i = *value; } Again some caution is in order. A global variable created in this manner will show up as a pointer in the target scripting language. It would be an extremely bad idea to free or destroy such a pointer. Also, C++ classes must supply a properly defined copy constructor in order for assignment to work correctly. 5.4.4 Linking to char *
When a global variable of type char *foo; SWIG generates the following code: /* C mode */ void foo_set(char *value) { if (foo) free(foo); foo = (char *) malloc(strlen(value)+1); strcpy(foo,value); } /* C++ mode. When -c++ option is used */ void foo_set(char *value) { if (foo) delete [] foo; foo = new char[strlen(value)+1]; strcpy(foo,value); }
If this is not the behavior that you want, consider making the variable read-only using the %inline %{ void set_foo(char *value) { strncpy(foo,value, 50); } %} Note: If you write an assist function like this, you will have to call it as a function from the target scripting language (it does not work like a variable). For example, in Python you will have to write: >>> set_foo("Hello World")
A common mistake with char *VERSION = "1.0";
In this case, the variable will be readable, but any attempt to change the value results in a segmentation or general protection fault. This is due to the fact that SWIG is trying to release the old value using char VERSION[64] = "1.0";
When variables of type example.i:20. Typemap warning. Setting const char * variable may leak memory
The reason for this behavior is that const char *foo = "Hello World\n";
Therefore, it's a really bad idea to call 5.4.5 ArraysArrays are fully supported by SWIG, but they are always handled as pointers instead of mapping them to a special array object or list in the target language. Thus, the following declarations : int foobar(int a[40]); void grok(char *argv[]); void transpose(double a[20][20]); are processed as if they were really declared like this: int foobar(int *a); void grok(char **argv); void transpose(double (*a)[20]); Like C, SWIG does not perform array bounds checking. It is up to the user to make sure the pointer points a suitably allocated region of memory. Multi-dimensional arrays are transformed into a pointer to an array of one less dimension. For example: int [10]; // Maps to int * int [10][20]; // Maps to int (*)[20] int [10][20][30]; // Maps to int (*)[20][30]
It is important to note that in the C type system, a multidimensional array Array variables are supported, but are read-only by default. For example: int a[100][200];
In this case, reading the variable 'a' returns a pointer of type %inline %{ void a_set(int i, int j, int val) { a[i][j] = val; } int a_get(int i, int j) { return a[i][j]; } %} To dynamically create arrays of various sizes and shapes, it may be useful to write some helper functions in your interface. For example: // Some array helpers %inline %{ /* Create any sort of [size] array */ int *int_array(int size) { return (int *) malloc(size*sizeof(int)); } /* Create a two-dimension array [size][10] */ int (*int_array_10(int size))[10] { return (int (*)[10]) malloc(size*10*sizeof(int)); } %}
Arrays of char pathname[256]; SWIG generates functions for both getting and setting the value that are equivalent to the following code: char *pathname_get() { return pathname; } void pathname_set(char *value) { strncpy(pathname,value,256); } In the target language, the value can be set like a normal variable. 5.4.6 Creating read-only variables
A read-only variable can be created by using the // File : interface.i int a; // Can read/write %immutable; int b,c,d // Read only variables %mutable; double x,y // read/write
The %immutable x; // Make x read-only ... double x; // Read-only (from earlier %immutable directive) double y; // Read-write ...
The #define %immutable %feature("immutable") #define %mutable %feature("immutable","") If you wanted to make all wrapped variables read-only, barring one or two, it might be easier to take this approach: %immutable; // Make all variables read-only %feature("immutable","0") x; // except, make x read/write ... double x; double y; double z; ...
Read-only variables are also created when declarations are declared as const int foo; /* Read only variable */ char * const version="1.0"; /* Read only variable */
Compatibility note: Read-only access used to be controlled by a pair of directives 5.4.7 Renaming and ignoring declarations
Normally, the name of a C declaration is used when that declaration is wrapped into the target language. However, this may generate a conflict with a keyword or already existing function in the scripting language. To resolve a name conflict, you can use the // interface.i %rename(my_print) print; extern void print(char *); %rename(foo) a_really_long_and_annoying_name; extern int a_really_long_and_annoying_name;
SWIG still calls the correct C function, but in this case the function
The placement of the // interface.i %rename(my_print) print; %rename(foo) a_really_long_and_annoying_name; %include "header.h"
%rename(output) print; // Rename all `print' functions to `output' SWIG does not normally perform any checks to see if the functions it wraps are already defined in the target scripting language. However, if you are careful about namespaces and your use of modules, you can usually avoid these problems.
Closely related to %ignore print; // Ignore all declarations named print %ignore _HAVE_FOO_H; // Ignore an include guard constant ... %include "foo.h" // Grab a header file ...
Any function, variable etc which matches
More powerful variants of
Compatibility note: Older versions of SWIG provided a special %name(output) extern void print(char *);
This directive is still supported, but it is deprecated and should probably be avoided. The 5.4.8 Default/optional argumentsSWIG supports default arguments in both C and C++ code. For example: int plot(double x, double y, int color=WHITE); In this case, SWIG generates wrapper code where the default arguments are optional in the target language. For example, this function could be used in Tcl as follows : % plot -3.4 7.5 # Use default value % plot -3.4 7.5 10 # set color to 10 instead Although the ANSI C standard does not allow default arguments, default arguments specified in a SWIG interface work with both C and C++. Note: There is a subtle semantic issue concerning the use of default arguments and the SWIG generated wrapper code. When default arguments are used in C code, the default values are emitted into the wrappers and the function is invoked with a full set of arguments. This is different to when wrapping C++ where an overloaded wrapper method is generated for each defaulted argument. Please refer to the section on default arguments in the C++ chapter for further details. 5.4.9 Pointers to functions and callbacksOccasionally, a C library may include functions that expect to receive pointers to functions–possibly to serve as callbacks. SWIG provides full support for function pointers provided that the callback functions are defined in C and not in the target language. For example, consider a function like this: int binary_op(int a, int b, int (*op)(int,int)); When you first wrap something like this into an extension module, you may find the function to be impossible to use. For instance, in Python: >>> def add(x,y): ... return x+y ... >>> binary_op(3,4,add) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Type error. Expected _p_f_int_int__int >>>
The reason for this error is that SWIG doesn't know how to map a scripting language function into a C callback. However, existing C functions can be used as arguments provided you install them as constants. One way to do this is to use the /* Function with a callback */ int binary_op(int a, int b, int (*op)(int,int)); /* Some callback functions */ %constant int add(int,int); %constant int sub(int,int); %constant int mul(int,int);
In this case, >>> binary_op(3,4,add) 7 >>> binary_op(3,4,mul) 12 >>> Unfortunately, by declaring the callback functions as constants, they are no longer accessible as functions. For example: >>> add(3,4) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object is not callable: '_ff020efc_p_f_int_int__int' >>>
If you want to make a function available as both a callback function and a function, you can use the /* Function with a callback */ int binary_op(int a, int b, int (*op)(int,int)); /* Some callback functions */ %callback("%s_cb"); int add(int,int); int sub(int,int); int mul(int,int); %nocallback;
The argument to >>> binary_op(3,4,add_cb) 7 >>> binary_op(3,4,mul_cb) 12 >>> add(3,4) 7 >>> mul(3,4) 12
Notice that when the function is used as a callback, special names such as
SWIG provides a number of extensions to standard C printf formatting that may be useful in this context. For instance, the following variation installs the callbacks as all upper-case constants such as /* Some callback functions */ %callback("%(upper)s"); int add(int,int); int sub(int,int); int mul(int,int); %nocallback;
A format string of And now, a final note about function pointer support. Although SWIG does not normally allow callback functions to be written in the target language, this can be accomplished with the use of typemaps and other advanced SWIG features. This is described in a later chapter. 5.5 Structures and unionsThis section describes the behavior of SWIG when processing ANSI C structures and union declarations. Extensions to handle C++ are described in the next section. If SWIG encounters the definition of a structure or union, it creates a set of accessor functions. Although SWIG does not need structure definitions to build an interface, providing definitions make it possible to access structure members. The accessor functions generated by SWIG simply take a pointer to an object and allow access to an individual member. For example, the declaration : struct Vector { double x,y,z; } gets transformed into the following set of accessor functions : double Vector_x_get(struct Vector *obj) { return obj->x; } double Vector_y_get(struct Vector *obj) { return obj->y; } double Vector_z_get(struct Vector *obj) { return obj->z; } void Vector_x_set(struct Vector *obj, double value) { obj->x = value; } void Vector_y_set(struct Vector *obj, double value) { obj->y = value; } void Vector_z_set(struct Vector *obj, double value) { obj->z = value; } In addition, SWIG creates default constructor and destructor functions if none are defined in the interface. For example: struct Vector *new_Vector() { return (Vector *) calloc(1,sizeof(struct Vector)); } void delete_Vector(struct Vector *obj) { free(obj); } Using these low-level accessor functions, an object can be minimally manipulated from the target language using code like this: v = new_Vector() Vector_x_set(v,2) Vector_y_set(v,10) Vector_z_set(v,-5) ... delete_Vector(v) However, most of SWIG's language modules also provide a high-level interface that is more convenient. Keep reading. 5.5.1 Typedef and structuresSWIG supports the following construct which is quite common in C programs : typedef struct { double x,y,z; } Vector;
When encountered, SWIG assumes that the name of the object is `Vector' and creates accessor functions like before. The only difference is that the use of double Vector_x_get(Vector *obj) { return obj->x; } If two different names are used like this : typedef struct vector_struct { double x,y,z; } Vector;
the name 5.5.2 Character strings and structures
Structures involving character strings require some care. SWIG assumes that all members of type %module mymodule ... struct Foo { char *name; ... } This results in the following accessor functions : char *Foo_name_get(Foo *obj) { return Foo->name; } char *Foo_name_set(Foo *obj, char *c) { if (obj->name) free(obj->name); obj->name = (char *) malloc(strlen(c)+1); strcpy(obj->name,c); return obj->name; } If this behavior differs from what you need in your applications, the SWIG “memberin” typemap can be used to change it. See the typemaps chapter for further details.
Note: If the 5.5.3 Array membersArrays may appear as the members of structures, but they will be read-only. SWIG will write an accessor function that returns the pointer to the first element of the array, but will not write a function to change the contents of the array itself. When this situation is detected, SWIG may generate a warning message such as the following : interface.i:116. Warning. Array member will be read-only To eliminate the warning message, typemaps can be used, but this is discussed in a later chapter. In many cases, the warning message is harmless. 5.5.4 Structure data membersOccasionally, a structure will contain data members that are themselves structures. For example: typedef struct Foo { int x; } Foo; typedef struct Bar { int y; Foo f; /* struct member */ } Bar;
When a structure member is wrapped, it is handled as a pointer, unless the Foo *Bar_f_get(Bar *b) { return &b->f; } void Bar_f_set(Bar *b, Foo *value) { b->f = *value; }
The reasons for this are somewhat subtle but have to do with the problem of modifying and accessing data inside the data member. For example, suppose you wanted to modify the value of Bar *b; b->f.x = 37; Translating this assignment to function calls (as would be used inside the scripting language interface) results in the following code: Bar *b; Foo_x_set(Bar_f_get(b),37);
In this code, if the It should be noted that this transformation to pointers only occurs if SWIG knows that a data member is a structure or class. For instance, if you had a structure like this, struct Foo { WORD w; };
and nothing was known about WORD Foo_w_get(Foo *f) { return f->w; } void Foo_w_set(FOO *f, WORD value) { f->w = value; }
Compatibility Note: SWIG-1.3.11 and earlier releases transformed all non-primitive member datatypes to pointers. Starting in SWIG-1.3.12, this transformation only occurs if a datatype is known to be a structure, class, or union. This is unlikely to break existing code. However, if you need to tell SWIG that an undeclared datatype is really a struct, simply use a forward struct declaration such as 5.5.5 C constructors and destructors
When wrapping structures, it is generally useful to have a mechanism for creating and destroying objects. If you don't do anything, SWIG will automatically generate functions for creating and destroying objects using
If you don't want SWIG to generate default constructors for your interfaces, you can use the swig -nodefaultctor example.i or %module foo ... %nodefaultctor; // Don't create default constructors ... declarations ... %clearnodefaultctor; // Re-enable default constructors
If you need more precise control, %nodefaultctor Foo; // No default constructor for Foo ... struct Foo { // No default constructor generated. }; struct Bar { // Default constructor generated. };
Since ignoring the implicit or default destructors most of the times produce memory leaks, SWIG will always try to generate them. If needed, however, you can selectively disable the generation of the default/implicit destructor by using %nodefaultdtor Foo; // No default/implicit destructor for Foo ... struct Foo { // No default destructor is generated. }; struct Bar { // Default destructor generated. };
Compatibility note: Prior to SWIG-1.3.7, SWIG did not generate default constructors or destructors unless you explicitly turned them on using
Note: There are also the 5.5.6 Adding member functions to C structures
Most languages provide a mechanism for creating classes and supporting object oriented programming. From a C standpoint, object oriented programming really just boils down to the process of attaching functions to structures. These functions normally operate on an instance of the structure (or object). Although there is a natural mapping of C++ to such a scheme, there is no direct mechanism for utilizing it with C code. However, SWIG provides a special /* file : vector.h */ ... typedef struct { double x,y,z; } Vector;
You can make a // file : vector.i %module mymodule %{ #include "vector.h" %} %include "vector.h" // Just grab original C header file %extend Vector { // Attach these functions to struct Vector Vector(double x, double y, double z) { Vector *v; v = (Vector *) malloc(sizeof(Vector)); v->x = x; v->y = y; v->z = z; return v; } ~Vector() { free($self); } double magnitude() { return sqrt($self->x*$self->x+$self->y*$self->y+$self->z*$self->z); } void print() { printf("Vector [%g, %g, %g]\n", $self->x,$self->y,$self->z); } };
Note the usage of the Now, when used with proxy classes in Python, you can do things like this : >>> v = Vector(3,4,0) # Create a new vector >>> print v.magnitude() # Print magnitude 5.0 >>> v.print() # Print it out [ 3, 4, 0 ] >>> del v # Destroy it
The // file : vector.i %module mymodule %{ #include "vector.h" %} typedef struct { double x,y,z; %extend { Vector(double x, double y, double z) { ... } ~Vector() { ... } ... } } Vector;
Finally, /* File : vector.c */ /* Vector methods */ #include "vector.h" Vector *new_Vector(double x, double y, double z) { Vector *v; v = (Vector *) malloc(sizeof(Vector)); v->x = x; v->y = y; v->z = z; return v; } void delete_Vector(Vector *v) { free(v); } double Vector_magnitude(Vector *v) { return sqrt(v->x*v->x+v->y*v->y+v->z*v->z); } // File : vector.i // Interface file %module mymodule %{ #include "vector.h" %} typedef struct { double x,y,z; %extend { Vector(int,int,int); // This calls new_Vector() ~Vector(); // This calls delete_Vector() double magnitude(); // This will call Vector_magnitude() ... } } Vector;
A little known feature of the // Add a new attribute to Vector %extend Vector { const double magnitude; } // Now supply the implementation of the Vector_magnitude_get function %{ const double Vector_magnitude_get(Vector *v) { return (const double) return sqrt(v->x*v->x+v->y*v->y+v->z*v->z); } %}
Now, for all practical purposes, A similar technique can also be used to work with problematic data members. For example, consider this interface: struct Person { char name[50]; ... }
By default, the struct Person { %extend { char *name; } ... } // Specific implementation of set/get functions %{ char *Person_name_get(Person *p) { return p->name; } void Person_name_set(Person *p, char *val) { strncpy(p->name,val,50); } %}
Finally, it should be stressed that even though
Compatibility note: The 5.5.7 Nested structuresOccasionally, a C program will involve structures like this : typedef struct Object { int objtype; union { int ivalue; double dvalue; char *strvalue; void *ptrvalue; } intRep; } Object; When SWIG encounters this, it performs a structure splitting operation that transforms the declaration into the equivalent of the following: typedef union { int ivalue; double dvalue; char *strvalue; void *ptrvalue; } Object_intRep; typedef struct Object { int objType; Object_intRep intRep; } Object;
SWIG will then create an Object_intRep *Object_intRep_get(Object *o) { return (Object_intRep *) &o->intRep; } int Object_intRep_ivalue_get(Object_intRep *o) { return o->ivalue; } int Object_intRep_ivalue_set(Object_intRep *o, int value) { return (o->ivalue = value); } double Object_intRep_dvalue_get(Object_intRep *o) { return o->dvalue; } ... etc ... Although this process is a little hairy, it works like you would expect in the target scripting language–especially when proxy classes are used. For instance, in Perl: # Perl5 script for accessing nested member $o = CreateObject(); # Create an object somehow $o->{intRep}->{ivalue} = 7 # Change value of o.intRep.ivalue If you have a lot nested structure declarations, it is advisable to double-check them after running SWIG. Although, there is a good chance that they will work, you may have to modify the interface file in certain cases. 5.5.8 Other things to note about structure wrapping
SWIG doesn't care if the declaration of a structure in a Starting with SWIG1.3, a number of improvements have been made to SWIG's code generator. Specifically, even though structure access has been described in terms of high-level accessor functions such as this, double Vector_x_get(Vector *v) { return v->x; }
most of the generated code is actually inlined directly into wrapper functions. Therefore, no function static int _wrap_Vector_x_get(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct Vector *arg1 ; double result ; if (SWIG_GetArgs(interp, objc, objv,"p:Vector_x_get self ",&arg0, SWIGTYPE_p_Vector) == TCL_ERROR) return TCL_ERROR; result = (double ) (arg1->x); Tcl_SetObjResult(interp,Tcl_NewDoubleObj((double) result)); return TCL_OK; }
The only exception to this rule are methods defined with Finally, it is important to note that most language modules may choose to build a more advanced interface. Although you may never use the low-level interface described here, most of SWIG's language modules use it in some way or another. 5.6 Code InsertionSometimes it is necessary to insert special code into the resulting wrapper file generated by SWIG. For example, you may want to include additional C code to perform initialization or other operations. There are four common ways to insert code, but it's useful to know how the output of SWIG is structured first. 5.6.1 The output of SWIGWhen SWIG creates its output file, it is broken up into four sections corresponding to runtime code, headers, wrapper functions, and module initialization code (in that order).
5.6.2 Code insertion blocksCode is inserted into the appropriate code section by using one of the code insertion directives listed below. The order of the sections in the wrapper file is as shown: %begin %{ ... code in begin section ... %} %runtime %{ ... code in runtime section ... %} %header %{ ... code in header section ... %} %wrapper %{ ... code in wrapper section ... %} %init %{ ... code in init section ... %}
The bare
The %module mymodule %{ #include "my_header.h" %} ... Declare functions here %{ void some_extra_function() { ... } %} A common use for code blocks is to write “helper” functions. These are functions that are used specifically for the purpose of building an interface, but which are generally not visible to the normal C program. For example : %{ /* Create a new vector */ static Vector *new_Vector() { return (Vector *) malloc(sizeof(Vector)); } %} // Now wrap it Vector *new_Vector(); 5.6.3 Inlined code blocksSince the process of writing helper functions is fairly common, there is a special inlined form of code block that is used as follows : %inline %{ /* Create a new vector */ Vector *new_Vector() { return (Vector *) malloc(sizeof(Vector)); } %}
The 5.6.4 Initialization blocks
When code is included in the %init %{ init_variables(); %} 5.7 An Interface Building StrategyThis section describes the general approach for building interface with SWIG. The specifics related to a particular scripting language are found in later chapters. 5.7.1 Preparing a C program for SWIGSWIG doesn't require modifications to your C code, but if you feed it a collection of raw C header files or source code, the results might not be what you expect—in fact, they might be awful. Here's a series of steps you can follow to make an interface for a C program :
Although this may sound complicated, the process turns out to be fairly easy once you get the hang of it. In the process of building an interface, SWIG may encounter syntax errors or other problems. The best way to deal with this is to simply copy the offending code into a separate interface file and edit it. However, the SWIG developers have worked very hard to improve the SWIG parser–you should report parsing errors to the swig-devel mailing list or to the SWIG bug tracker. 5.7.2 The SWIG interface fileThe preferred method of using SWIG is to generate separate interface file. Suppose you have the following C header file : /* File : header.h */ #include <stdio.h> #include <math.h> extern int foo(double); extern double bar(int, int); extern void dump(FILE *f); A typical SWIG interface file for this header file would look like the following : /* File : interface.i */ %module mymodule %{ #include "header.h" %} extern int foo(double); extern double bar(int, int); extern void dump(FILE *f); Of course, in this case, our header file is pretty simple so we could use a simpler approach and use an interface file like this: /* File : interface.i */ %module mymodule %{ #include "header.h" %} %include "header.h"
The main advantage of this approach is minimal maintenance of an interface file for when the header file changes in the future. In more complex projects, an interface file containing numerous 5.7.3 Why use separate interface files?
Although SWIG can parse many header files, it is more common to write a special
5.7.4 Getting the right header files
Sometimes, it is necessary to use certain header files in order for the code generated by SWIG to compile properly. Make sure you include certain header files by using a %module graphics %{ #include <GL/gl.h> #include <GL/glu.h> %} // Put rest of declarations here ... 5.7.5 What to do with main()
If your program defines a
Getting rid of
As a general note, many C programs only use the
Note: If some cases, you might be inclined to create a scripting language wrapper for 6 SWIG and C++This chapter describes SWIG's support for wrapping C++. As a prerequisite, you should first read the chapter SWIG Basics to see how SWIG wraps ANSI C. Support for C++ builds upon ANSI C wrapping and that material will be useful in understanding this chapter. 6.1 Comments on C++ WrappingBecause of its complexity and the fact that C++ can be difficult to integrate with itself let alone other languages, SWIG only provides support for a subset of C++ features. Fortunately, this is now a rather large subset. In part, the problem with C++ wrapping is that there is no semantically obvious (or automatic ) way to map many of its advanced features into other languages. As a simple example, consider the problem of wrapping C++ multiple inheritance to a target language with no such support. Similarly, the use of overloaded operators and overloaded functions can be problematic when no such capability exists in a target language.
A more subtle issue with C++ has to do with the way that some C++ programmers think about programming libraries. In the world of SWIG, you are really trying to create binary-level software components for use in other languages. In order for this to work, a “component” has to contain real executable instructions and there has to be some kind of binary linking mechanism for accessing its functionality. In contrast, C++ has increasingly relied upon generic programming and templates for much of its functionality. Although templates are a powerful feature, they are largely orthogonal to the whole notion of binary components and libraries. For example, an STL 6.2 ApproachTo wrap C++, SWIG uses a layered approach to code generation. At the lowest level, SWIG generates a collection of procedural ANSI-C style wrappers. These wrappers take care of basic type conversion, type checking, error handling, and other low-level details of the C++ binding. These wrappers are also sufficient to bind C++ into any target language that supports built-in procedures. In some sense, you might view this layer of wrapping as providing a C library interface to C++. On top of the low-level procedural (flattened) interface, SWIG generates proxy classes that provide a natural object-oriented (OO) interface to the underlying code. The proxy classes are typically written in the target language itself. For instance, in Python, a real Python class is used to provide a wrapper around the underlying C++ object. It is important to emphasize that SWIG takes a deliberately conservative and non-intrusive approach to C++ wrapping. SWIG does not encapsulate C++ classes inside a special C++ adaptor, it does not rely upon templates, nor does it add in additional C++ inheritance when generating wrappers. The last thing that most C++ programs need is even more compiler magic. Therefore, SWIG tries to maintain a very strict and clean separation between the implementation of your C++ application and the resulting wrapper code. You might say that SWIG has been written to follow the principle of least surprise–it does not play sneaky tricks with the C++ type system, it doesn't mess with your class hierarchies, and it doesn't introduce new semantics. Although this approach might not provide the most seamless integration with C++, it is safe, simple, portable, and debuggable. Some of this chapter focuses on the low-level procedural interface to C++ that is used as the foundation for all language modules. Keep in mind that the target languages also provide the high-level OO interface via proxy classes. More detailed coverage can be found in the documentation for each target language. 6.3 Supported C++ featuresSWIG currently supports most C++ features including the following:
The following C++ features are not currently supported:
As a rule of thumb, SWIG should not be used on raw C++ source files, use header files only. SWIG's C++ support is an ongoing project so some of these limitations may be lifted in future releases. However, we make no promises. Also, submitting a bug report is a very good way to get problems fixed (wink). 6.4 Command line options and compilation
When wrapping C++ code, it is critical that SWIG be called with the ` When compiling and linking the resulting wrapper file, it is normal to use the C++ compiler. For example: $ swig -c++ -tcl example.i $ c++ -c example_wrap.cxx $ c++ example_wrap.o $(OBJS) -o example.so Unfortunately, the process varies slightly on each platform. Make sure you refer to the documentation on each target language for further details. The SWIG Wiki also has further details.
Compatibility Note: Early versions of SWIG generated just a flattened low-level C style API to C++ classes by default. The 6.5 Proxy classesIn order to provide a natural mapping from C++ classes to the target language classes, SWIG's target languages mostly wrap C++ classes with special proxy classes. These proxy classes are typically implemented in the target language itself. For example, if you're building a Python module, each C++ class is wrapped by a Python proxy class. Or if you're building a Java module, each C++ class is wrapped by a Java proxy class. 6.5.1 Construction of proxy classesProxy classes are always constructed as an extra layer of wrapping that uses low-level accessor functions. To illustrate, suppose you had a C++ class like this: class Foo { public: Foo(); ~Foo(); int bar(int x); int x; }; Using C++ as pseudocode, a proxy class looks something like this: class FooProxy { private: Foo *self; public: FooProxy() { self = new_Foo(); } ~FooProxy() { delete_Foo(self); } int bar(int x) { return Foo_bar(self,x); } int x_get() { return Foo_x_get(self); } void x_set(int x) { Foo_x_set(self,x); } }; Of course, always keep in mind that the real proxy class is written in the target language. For example, in Python, the proxy might look roughly like this: class Foo: def __init__(self): self.this = new_Foo() def __del__(self): delete_Foo(self.this) def bar(self,x): return Foo_bar(self.this,x) def __getattr__(self,name): if name == 'x': return Foo_x_get(self.this) ... def __setattr__(self,name,value): if name == 'x': Foo_x_set(self.this,value) ... Again, it's important to emphasize that the low-level accessor functions are always used by the proxy classes. Whenever possible, proxies try to take advantage of language features that are similar to C++. This might include operator overloading, exception handling, and other features. 6.5.2 Resource management in proxiesA major issue with proxies concerns the memory management of wrapped objects. Consider the following C++ code: class Foo { public: Foo(); ~Foo(); int bar(int x); int x; }; class Spam { public: Foo *value; ... }; Consider some script code that uses these classes: f = Foo() # Creates a new Foo s = Spam() # Creates a new Spam s.value = f # Stores a reference to f inside s g = s.value # Returns stored reference g = 4 # Reassign g to some other value del f # Destroy f
Now, ponder the resulting memory management issues. When objects are created in the script, the objects are wrapped by newly created proxy classes. That is, there is both a new proxy class instance and a new instance of the underlying C++ class. In this example, both
Finally, consider what happens when objects are destroyed. In the statement, To deal with memory management problems, proxy classes provide an API for controlling ownership. In C++ pseudocode, ownership control might look roughly like this: class FooProxy { public: Foo *self; int thisown; FooProxy() { self = new_Foo(); thisown = 1; // Newly created object } ~FooProxy() { if (thisown) delete_Foo(self); } ... // Ownership control API void disown() { thisown = 0; } void acquire() { thisown = 1; } }; class FooPtrProxy: public FooProxy { public: FooPtrProxy(Foo *s) { self = s; thisown = 0; } }; class SpamProxy { ... FooProxy *value_get() { return FooPtrProxy(Spam_value_get(self)); } void value_set(FooProxy *v) { Spam_value_set(self,v->self); v->disown(); } ... }; Looking at this code, there are a few central features:
Given the tricky nature of C++ memory management, it is impossible for proxy classes to automatically handle every possible memory management problem. However, proxies do provide a mechanism for manual control that can be used (if necessary) to address some of the more tricky memory management problems. 6.5.3 Language specific detailsLanguage specific details on proxy classes are contained in the chapters describing each target language. This chapter has merely introduced the topic in a very general way. 6.6 Simple C++ wrappingThe following code shows a SWIG interface file for a simple C++ class. %module list %{ #include "list.h" %} // Very simple C++ example for linked list class List { public: List(); ~List(); int search(char *value); void insert(char *); void remove(char *); char *get(int n); int length; static void print(List *l); }; To generate wrappers for this class, SWIG first reduces the class to a collection of low-level C-style accessor functions which are then used by the proxy classes. 6.6.1 Constructors and destructorsC++ constructors and destructors are translated into accessor functions such as the following : List * new_List(void) { return new List; } void delete_List(List *l) { delete l; } 6.6.2 Default constructors, copy constructors and implicit destructorsFollowing the C++ rules for implicit constructor and destructors, SWIG will automatically assume there is one even when they are not explicitly declared in the class interface. In general then:
And as in C++, a few rules that alters the previous behavior:
SWIG should never generate a default constructor, copy constructor or default destructor wrapper for a class in which it is illegal to do so. In some cases, however, it could be necessary (if the complete class declaration is not visible from SWIG, and one of the above rules is violated) or desired (to reduce the size of the final interface) by manually disabling the implicit constructor/destructor generation.
To manually disable these, the For example: %nodefaultctor Foo; // Disable the default constructor for class Foo. class Foo { // No default constructor is generated, unless one is declared ... }; class Bar { // A default constructor is generated, if possible ... };
The directive %nodefaultctor; // Disable creation of default constructors class Foo { // No default constructor is generated, unless one is declared ... }; class Bar { public: Bar(); // The default constructor is generated, since one is declared }; %clearnodefaultctor; // Enable the creation of default constructors again
The corresponding %nodefaultdtor Foo; // Disable the implicit/default destructor for class Foo. class Foo { // No destructor is generated, unless one is declared ... };
Compatibility Note: The generation of default constructors/implicit destructors was made the default behavior in SWIG 1.3.7. This may break certain older modules, but the old behavior can be easily restored using
Note: The 6.6.3 When constructor wrappers aren't createdIf a class defines a constructor, SWIG normally tries to generate a wrapper for it. However, SWIG will not generate a constructor wrapper if it thinks that it will result in illegal wrapper code. There are really two cases where this might show up. First, SWIG won't generate wrappers for protected or private constructors. For example: class Foo { protected: Foo(); // Not wrapped. public: ... }; Next, SWIG won't generate wrappers for a class if it appears to be abstract–that is, it has undefined pure virtual methods. Here are some examples: class Bar { public: Bar(); // Not wrapped. Bar is abstract. virtual void spam(void) = 0; }; class Grok : public Bar { public: Grok(); // Not wrapped. No implementation of abstract spam(). }; Some users are surprised (or confused) to find missing constructor wrappers in their interfaces. In almost all cases, this is caused when classes are determined to be abstract. To see if this is the case, run SWIG with all of its warnings turned on: % swig -Wall -python module.i In this mode, SWIG will issue a warning for all abstract classes. It is possible to force a class to be non-abstract using this: %feature("notabstract") Foo; class Foo : public Bar { public: Foo(); // Generated no matter what---not abstract. ... };
More information about 6.6.4 Copy constructorsIf a class defines more than one constructor, its behavior depends on the capabilities of the target language. If overloading is supported, the copy constructor is accessible using the normal constructor function. For example, if you have this: class List { public: List(); List(const List &); // Copy constructor ... }; then the copy constructor can be used as follows: x = List() # Create a list y = List(x) # Copy list x If the target language does not support overloading, then the copy constructor is available through a special function like this: List *copy_List(List *f) { return new List(*f); }
Note: For a class
Note: SWIG does not generate a copy constructor wrapper unless one is explicitly declared in the class. This differs from the treatment of default constructors and destructors. However, copy constructor wrappers can be generated if using the %copyctor List; class List { public: List(); };
Will generate a copy constructor wrapper for Compatibility note: Special support for copy constructors was not added until SWIG-1.3.12. In previous versions, copy constructors could be wrapped, but they had to be renamed. For example: class Foo { public: Foo(); %name(CopyFoo) Foo(const Foo &); ... };
For backwards compatibility, SWIG does not perform any special copy-constructor handling if the constructor has been manually renamed. For instance, in the above example, the name of the constructor is set to 6.6.5 Member functionsAll member functions are roughly translated into accessor functions like this : int List_search(List *obj, char *value) { return obj->search(value); }
This translation is the same even if the member function has been declared as
It should be noted that SWIG does not actually create a C accessor function in the code it generates. Instead, member access such as 6.6.6 Static members
Static member functions are called directly without making any special transformations. For example, the static member function 6.6.7 Member dataMember data is handled in exactly the same manner as for C structures. A pair of accessor functions are effectively created. For example : int List_length_get(List *obj) { return obj->length; } int List_length_set(List *obj, int value) { obj->length = value; return value; }
A read-only member can be created using the class List { public: ... %immutable; int length; %mutable; ... }; Alternatively, you can specify an immutable member in advance like this: %immutable List::length; ... class List { ... int length; // Immutable by above directive ... };
Similarly, all data attributes declared as There are some subtle issues when wrapping data members that are themselves classes. For instance, if you had another class like this, class Foo { public: List items; ...
then the low-level accessor to the List *Foo_items_get(Foo *self) { return &self->items; } void Foo_items_set(Foo *self, List *value) { self->items = *value; } More information about this can be found in the SWIG Basics chapter, Structure data members section.
The wrapper code to generate the accessors for classes comes from the pointer typemaps. This can be somewhat unnatural for some types. For example, a user would expect the STL std::string class member variables to be wrapped as a string in the target language, rather than a pointer to this class. The const reference typemaps offer this type of marshalling, so there is a feature to tell SWIG to use the const reference typemaps rather than the pointer typemaps. It is the // All List variables will use const List& typemaps %naturalvar List; // Only Foo::myList will use const List& typemaps %naturalvar Foo::myList; struct Foo { List myList; }; // All variables will use const reference typemaps %naturalvar;
The observant reader will notice that const List &Foo_items_get(Foo *self) { return self->items; } void Foo_items_set(Foo *self, const List &value) { self->items = value; }
In fact it is generally a good idea to use this feature globally as the reference typemaps have extra NULL checking compared to the pointer typemaps. A pointer can be NULL, whereas a reference cannot, so the extra checking ensures that the target language user does not pass in a value that translates to a NULL pointer and thereby preventing any potential NULL pointer dereferences. The
Other alternatives for turning this feature on globally are to use the
Compatibility note: The
Compatibility note: Read-only access used to be controlled by a pair of directives Compatibility note: Prior to SWIG-1.3.12, all members of unknown type were wrapped into accessor functions using pointers. For example, if you had a structure like this struct Foo { size_t len; };
and nothing was known about 6.7 Default argumentsSWIG will wrap all types of functions that have default arguments. For example member functions: class Foo { public: void bar(int x, int y = 3, int z = 4); }; SWIG handles default arguments by generating an extra overloaded method for each defaulted argument. SWIG is effectively handling methods with default arguments as if it was wrapping the equivalent overloaded methods. Thus for the example above, it is as if we had instead given the following to SWIG: class Foo { public: void bar(int x, int y, int z); void bar(int x, int y); void bar(int x); }; The wrappers produced are exactly the same as if the above code was instead fed into SWIG. Details of this are covered later in the Wrapping Overloaded Functions and Methods section. This approach allows SWIG to wrap all possible default arguments, but can be verbose. For example if a method has ten default arguments, then eleven wrapper methods are generated.
Please see the Features and default arguments section for more information on using
Compatibility note: Versions of SWIG prior to SWIG-1.3.23 wrapped default arguments slightly differently. Instead a single wrapper method was generated and the default values were copied into the C++ wrappers so that the method being wrapped was then called with all the arguments specified. If the size of the wrappers are a concern then this approach to wrapping methods with default arguments can be re-activated by using the %feature("compactdefaultargs") Foo::bar; class Foo { public: void bar(int x, int y = 3, int z = 4); }; This is great for reducing the size of the wrappers, but the caveat is it does not work for the statically typed languages, such as C# and Java, which don't have optional arguments in the language, Another restriction of this feature is that it cannot handle default arguments that are not public. The following example illustrates this: class Foo { private: static const int spam; public: void bar(int x, int y = spam); // Won't work with %feature("compactdefaultargs") - // private default value }; This produces uncompileable wrapper code because default values in C++ are evaluated in the same scope as the member function whereas SWIG evaluates them in the scope of a wrapper function (meaning that the values have to be public). This feature is automatically turned on when wrapping C code with default arguments and whenever keyword arguments (kwargs) are specified for either C or C++ code. Keyword arguments are a language feature of some scripting languages, for example Ruby and Python. SWIG is unable to support kwargs when wrapping overloaded methods, so the default approach cannot be used. 6.8 Protection
SWIG wraps class members that are public following the C++ conventions, i.e., by explicit public declaration or by the use of the
By default, members of a class definition are assumed to be private until you explicitly give a ` 6.9 Enums and constantsEnumerations and constants are handled differently by the different language modules and are described in detail in the appropriate language chapter. However, many languages map enums and constants in a class definition into constants with the classname as a prefix. For example : class Swig { public: enum {ALE, LAGER, PORTER, STOUT}; }; Generates the following set of constants in the target scripting language : Swig_ALE = Swig::ALE Swig_LAGER = Swig::LAGER Swig_PORTER = Swig::PORTER Swig_STOUT = Swig::STOUT
Members declared as 6.10 FriendsFriend declarations are recognised by SWIG. For example, if you have this code: class Foo { public: ... friend void blah(Foo *f); ... };
then the class Foo { public: ... }; void blah(Foo *f); A friend declaration, as in C++, is understood to be in the same scope where the class is declared, hence, you can have %ignore bar::blah(Foo *f); namespace bar { class Foo { public: ... friend void blah(Foo *f); ... }; } and a wrapper for the method 'blah' will not be generated. 6.11 References and pointersC++ references are supported, but SWIG transforms them back into pointers. For example, a declaration like this : class Foo { public: double bar(double &a); } has a low-level accessor double Foo_bar(Foo *obj, double *a) { obj->bar(*a); }
As a special case, most language modules pass void foo(const int &x); it is called from a script as follows: foo(3) # Notice pass by value Functions that return a reference are remapped to return a pointer instead. For example: class Bar { public: Foo &spam(); }; Generates an accessor like this: Foo *Bar_spam(Bar *obj) { Foo &result = obj->spam(); return &result; }
However, functions that return const int &bar(); will return integers such as 37 or 42 in the target scripting language rather than a pointer to an integer. Don't return references to objects allocated as local variables on the stack. SWIG doesn't make a copy of the objects so this will probably cause your program to crash. Note: The special treatment for references to primitive datatypes is necessary to provide more seamless integration with more advanced C++ wrapping applications—especially related to templates and the STL. This was first added in SWIG-1.3.12. 6.12 Pass and return by valueOccasionally, a C++ program will pass and return class objects by value. For example, a function like this might appear: Vector cross_product(Vector a, Vector b);
If no information is supplied about Vector *wrap_cross_product(Vector *a, Vector *b) { Vector x = *a; Vector y = *b; Vector r = cross_product(x,y); return new Vector(r); }
In order for the wrapper code to compile,
If Vector cross_product(Vector *a, Vector *b) { SwigValueWrapper<Vector> x = *a; SwigValueWrapper<Vector> y = *b; SwigValueWrapper<Vector> r = cross_product(x,y); return new Vector(r); }
This transformation is a little sneaky, but it provides support for pass-by-value even when a class does not provide a default constructor and it makes it possible to properly support a number of SWIG's customization options. The definition of
Although SWIG usually detects the classes to which the Fulton Transform should be applied, in some situations it's necessary to override it. That's done with %feature("novaluewrapper") A; class A; %feature("valuewrapper") B; struct B { B(); // .... }; It is well worth considering turning this feature on for classes that do have a default constructor. It will remove a redundant constructor call at the point of the variable declaration in the wrapper, so will generate notably better performance for large objects or for classes with expensive construction. Alternatively consider returning a reference or a pointer. Note: this transformation has no effect on typemaps or any other part of SWIG—it should be transparent except that you may see this code when reading the SWIG output file. Note: This template transformation is new in SWIG-1.3.11 and may be refined in future SWIG releases. In practice, it is only absolutely necessary to do this for classes that don't define a default constructor. Note: The use of this template only occurs when objects are passed or returned by value. It is not used for C++ pointers or references. 6.13 InheritanceSWIG supports C++ inheritance of classes and allows both single and multiple inheritance, as limited or allowed by the target language. The SWIG type-checker knows about the relationship between base and derived classes and allows pointers to any object of a derived class to be used in functions of a base class. The type-checker properly casts pointer values and is safe to use with multiple inheritance. SWIG treats private or protected inheritance as close to the C++ spirit, and target language capabilities, as possible. In most cases, this means that SWIG will parse the non-public inheritance declarations, but that will have no effect in the generated code, besides the implicit policies derived for constructor and destructors. The following example shows how SWIG handles inheritance. For clarity, the full C++ code has been omitted. // shapes.i %module shapes %{ #include "shapes.h" %} class Shape { public: double x,y; virtual double area() = 0; virtual double perimeter() = 0; void set_location(double x, double y); }; class Circle : public Shape { public: Circle(double radius); ~Circle(); double area(); double perimeter(); }; class Square : public Shape { public: Square(double size); ~Square(); double area(); double perimeter(); } When wrapped into Python, we can perform the following operations (shown using the low level Python accessors): $ python >>> import shapes >>> circle = shapes.new_Circle(7) >>> square = shapes.new_Square(10) >>> print shapes.Circle_area(circle) 153.93804004599999757 >>> print shapes.Shape_area(circle) 153.93804004599999757 >>> print shapes.Shape_area(square) 100.00000000000000000 >>> shapes.Shape_set_location(square,2,-3) >>> print shapes.Shape_perimeter(square) 40.00000000000000000 >>>
In this example, Circle and Square objects have been created. Member functions can be invoked on each object by making calls to
One important point concerning inheritance is that the low-level accessor functions are only generated for classes in which they are actually declared. For instance, in the above example, the method Note that there is a one to one correlation between the low-level accessor functions and the proxy methods and therefore there is also a one to one correlation between the C++ class methods and the generated proxy class methods. Note: For the best results, SWIG requires all base classes to be defined in an interface. Otherwise, you may get a warning message like this: example.i:18: Warning(401): Nothing known about base class 'Foo'. Ignored.
If any base class is undefined, SWIG still generates correct type relationships. For instance, a function accepting a
Note: class Foo { ... }; typedef Foo FooObj; class Bar : public FooObj { // Ok. Base class is Foo ... };
Similarly, typedef struct { ... } Foo; class Bar : public Foo { // Ok. ... };
Compatibility Note: Starting in version 1.3.7, SWIG only generates low-level accessor wrappers for the declarations that are actually defined in each class. This differs from SWIG1.1 which used to inherit all of the declarations defined in base classes and regenerate specialized accessor functions such as 6.14 A brief discussion of multiple inheritance, pointers, and type checkingWhen a target scripting language refers to a C++ object, it normally uses a tagged pointer object that contains both the value of the pointer and a type string. For example, in Tcl, a C++ pointer might be encoded as a string like this: _808fea88_p_Circle A somewhat common question is whether or not the type-tag could be safely removed from the pointer. For instance, to get better performance, could you strip all type tags and just use simple integers instead?
In general, the answer to this question is no. In the wrappers, all pointers are converted into a common data representation in the target language. Typically this is the equivalent of casting a pointer to The problem with losing type information is that it is needed to properly support many advanced C++ features–especially multiple inheritance. For example, suppose you had code like this: class A { public: int x; }; class B { public: int y; }; class C : public A, public B { }; int A_function(A *a) { return a->x; } int B_function(B *b) { return b->y; }
Now, consider the following code that uses C *c = new C(); void *p = (void *) c; ... int x = A_function((A *) p); int y = B_function((B *) p);
In this code, both ------------ <--- (C *), (A *) | A | |------------| <--- (B *) | B | ------------
Because of this stacking, a pointer of type The use of type tags marks all pointers with the real type of the underlying object. This extra information is then used by SWIG generated wrappers to correctly cast pointer values under inheritance (avoiding the above problem).
Some of the language modules are able to solve the problem by storing multiple instances of the pointer, for example, C *c = new C(); void *p = (void *) c; void *pA = (void *) c; void *pB = (void *) c; ... int x = A_function((A *) pA); int y = B_function((B *) pB); In practice, the pointer is held as an integral number in the target language proxy class. 6.15 Wrapping Overloaded Functions and MethodsIn many language modules, SWIG provides partial support for overloaded functions, methods, and constructors. For example, if you supply SWIG with overloaded functions like this: void foo(int x) { printf("x is %d\n", x); } void foo(char *x) { printf("x is '%s'\n", x); } The function is used in a completely natural way. For example: >>> foo(3) x is 3 >>> foo("hello") x is 'hello' >>> Overloading works in a similar manner for methods and constructors. For example if you have this code, class Foo { public: Foo(); Foo(const Foo &); // Copy constructor void bar(int x); void bar(char *s, int y); }; it might be used like this >>> f = Foo() # Create a Foo >>> f.bar(3) >>> g = Foo(f) # Copy Foo >>> f.bar("hello",2) 6.15.1 Dispatch function generationThe implementation of overloaded functions and methods is somewhat complicated due to the dynamic nature of scripting languages. Unlike C++, which binds overloaded methods at compile time, SWIG must determine the proper function as a runtime check for scripting language targets. This check is further complicated by the typeless nature of certain scripting languages. For instance, in Tcl, all types are simply strings. Therefore, if you have two overloaded functions like this, void foo(char *x); void foo(int x); the order in which the arguments are checked plays a rather critical role. For statically typed languages, SWIG uses the language's method overloading mechanism. To implement overloading for the scripting languages, SWIG generates a dispatch function that checks the number of passed arguments and their types. To create this function, SWIG first examines all of the overloaded methods and ranks them according to the following rules:
—————- ———- TYPE * 0 (High) void * 20 Integers 40 Floating point 60 char 80 Strings 100 (Low) Using these precedence values, overloaded methods with the same number of required arguments are sorted in increased order of precedence values. This may sound very confusing, but an example will help. Consider the following collection of overloaded methods: void foo(double); void foo(int); void foo(Bar *); void foo(); void foo(int x, int y, int z, int w); void foo(int x, int y, int z = 3); void foo(double x, double y); void foo(double x, Bar *z); The first rule simply ranks the functions by required argument count. This would produce the following list: rank ----- [0] foo() [1] foo(double); [2] foo(int); [3] foo(Bar *); [4] foo(int x, int y, int z = 3); [5] foo(double x, double y) [6] foo(double x, Bar *z) [7] foo(int x, int y, int z, int w); The second rule, simply refines the ranking by looking at argument type precedence values. rank ----- [0] foo() [1] foo(Bar *); [2] foo(int); [3] foo(double); [4] foo(int x, int y, int z = 3); [5] foo(double x, Bar *z) [6] foo(double x, double y) [7] foo(int x, int y, int z, int w); Finally, to generate the dispatch function, the arguments passed to an overloaded method are simply checked in the same order as they appear in this ranking. If you're still confused, don't worry about it—SWIG is probably doing the right thing. 6.15.2 Ambiguity in OverloadingRegrettably, SWIG is not able to support every possible use of valid C++ overloading. Consider the following example: void foo(int x); void foo(long x);
In C++, this is perfectly legal. However, in a scripting language, there is generally only one kind of integer object. Therefore, which one of these functions do you pick? Clearly, there is no way to truly make a distinction just by looking at the value of the integer itself ( example.i:4: Warning(509): Overloaded foo(long) is shadowed by foo(int) at example.i:3. or for statically typed languages like Java: example.i:4: Warning(516): Overloaded method foo(long) ignored. Method foo(int) at example.i:3 used. This means that the second overloaded function will be inaccessible from a scripting interface or the method won't be wrapped at all. This is done as SWIG does not know how to disambiguate it from an earlier method. Ambiguity problems are known to arise in the following situations:
When an ambiguity arises, methods are checked in the same order as they appear in the interface file. Therefore, earlier methods will shadow methods that appear later. When wrapping an overloaded function, there is a chance that you will get an error message like this: example.i:3: Warning(467): Overloaded foo(int) not supported (no type checking rule for 'int'). This error means that the target language module supports overloading, but for some reason there is no type-checking rule that can be used to generate a working dispatch function. The resulting behavior is then undefined. You should report this as a bug to the SWIG bug tracking database. If you get an error message such as the following, foo.i:6. Overloaded declaration ignored. Spam::foo(double ) foo.i:5. Previous declaration is Spam::foo(int ) foo.i:7. Overloaded declaration ignored. Spam::foo(Bar *,Spam *,int ) foo.i:5. Previous declaration is Spam::foo(int ) it means that the target language module has not yet implemented support for overloaded functions and methods. The only way to fix the problem is to read the next section. 6.15.3 Ambiguity resolution and renaming
If an ambiguity in overload resolution occurs or if a module doesn't allow overloading, there are a few strategies for dealing with the problem. First, you can tell SWIG to ignore one of the methods. This is easy—simply use the %ignore foo(long); void foo(int); void foo(long); // Ignored. Oh well.
The other alternative is to rename one of the methods. This can be done using %rename("foo_short") foo(short); %rename(foo_long) foo(long); void foo(int); void foo(short); // Accessed as foo_short() void foo(long); // Accessed as foo_long()
Note that the quotes around the new name are optional, however, should the new name be a C/C++ keyword they would be essential in order to avoid a parsing error. The /* Forward renaming declarations */ %rename(foo_i) foo(int); %rename(foo_d) foo(double); ... void foo(int); // Becomes 'foo_i' void foo(char *c); // Stays 'foo' (not renamed) class Spam { public: void foo(int); // Becomes 'foo_i' void foo(double); // Becomes 'foo_d' ... }; If you only want the renaming to apply to a certain scope, the C++ scope resolution operator (::) can be used. For example: %rename(foo_i) ::foo(int); // Only rename foo(int) in the global scope. // (will not rename class members) %rename(foo_i) Spam::foo(int); // Only rename foo(int) in class Spam
When a renaming operator is applied to a class as in %rename(foo_i) Spam::foo(int); %rename(foo_d) Spam::foo(double); class Spam { public: virtual void foo(int); // Renamed to foo_i virtual void foo(double); // Renamed to foo_d ... }; class Bar : public Spam { public: virtual void foo(int); // Renamed to foo_i virtual void foo(double); // Renamed to foo_d ... }; class Grok : public Bar { public: virtual void foo(int); // Renamed to foo_i virtual void foo(double); // Renamed to foo_d ... };
It is also possible to include class Spam { %rename(foo_i) foo(int); %rename(foo_d) foo(double); public: virtual void foo(int); // Renamed to foo_i virtual void foo(double); // Renamed to foo_d ... }; class Bar : public Spam { public: virtual void foo(int); // Renamed to foo_i virtual void foo(double); // Renamed to foo_d ... };
In this case, the
A special form of %rename(foo_i) *::foo(int); // Only rename foo(int) if it appears in a class.
Note: the
Although this discussion has primarily focused on %ignore foo(double); // Ignore all foo(double) %ignore Spam::foo; // Ignore foo in class Spam %ignore Spam::foo(double); // Ignore foo(double) in class Spam %ignore *::foo(double); // Ignore foo(double) in all classes
When applied to a base class, Notes on %rename and %ignore:
%module foo /* Rename these overloaded functions */ %rename(foo_i) foo(int); %rename(foo_d) foo(double); %include “header.h”
%rename(bar) Spam::foo; // Rename foo to bar in class Spam only %rename(bar) *::foo; // Rename foo in classes only
%rename(foo_i) Spam::foo(int);
%rename(Foo) Spam::foo;
and this %rename(Foo) Spam::foo;
%rename(bar) foo;
%rename(foo_i) Spam::foo(int);
(the declarations are not stored in a linked list and order has no importance). Of course, a repeated
public: ... void bar() const; ...
};
the declaration %rename(name) Spam::bar();
will not apply as there is no unqualified member ... void bar(); %%//%% Unqualified member void bar() const; %%//%% Qualified member ...
};
%rename can then be used to target each of the overloaded methods individually. For example we can give them separate names in the target language: %rename(name1) Spam::bar();
%rename(name2) Spam::bar() const;
Similarly, if you merely wanted to ignore one of the declarations, use
%rename(foo_i) foo(int); class Spam { public: void foo(Integer); %%//%% Stays 'foo' (not renamed) }; class Ham { public: void foo(int); %%//%% Renamed to foo_i };
public: ... void bar(int i=-1, double d=0.0); ...
};
The following 6.15.4 Comments on overloadingSupport for overloaded methods was first added in SWIG-1.3.14. The implementation is somewhat unusual when compared to similar tools. For instance, the order in which declarations appear is largely irrelevant in SWIG. Furthermore, SWIG does not rely upon trial execution or exception handling to figure out which method to invoke. Internally, the overloading mechanism is completely configurable by the target language module. Therefore, the degree of overloading support may vary from language to language. As a general rule, statically typed languages like Java are able to provide more support than dynamically typed languages like Perl, Python, Ruby, and Tcl. 6.16 Wrapping overloaded operatorsC++ overloaded operator declarations can be wrapped. For example, consider a class like this: 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) { rpart = c.rpart; ipart = c.ipart; return *this; } Complex operator+(const Complex &c) const { return Complex(rpart+c.rpart, ipart+c.ipart); } Complex operator-(const Complex &c) const { return Complex(rpart-c.rpart, ipart-c.ipart); } Complex operator*(const Complex &c) const { return Complex(rpart*c.rpart - ipart*c.ipart, rpart*c.ipart + c.rpart*ipart); } Complex operator-() const { return Complex(-rpart, -ipart); } double re() const { return rpart; } double im() const { return ipart; } };
When operator declarations appear, they are handled in exactly the same manner as regular methods. However, the names of these methods are set to strings like “
Some language modules already know how to automatically handle certain operators (mapping them into operators in the target language). However, the underlying implementation of this is really managed in a very general way using the %rename(__add__) Complex::operator+;
This binds the + operator to a method called _wrap_Complex___add__(args) { ... get args ... obj->operator+(args); ... } When used in the target language, it may now be possible to use the overloaded operator normally. For example: >>> a = Complex(3,4) >>> b = Complex(5,2) >>> c = a + b # Invokes __add__ method
It is important to realize that there is nothing magical happening here. The %rename(add) operator+; The resulting scripting interface might work like this: a = Complex(3,4) b = Complex(5,2) c = a.add(b) # Call a.operator+(b) All of the techniques described to deal with overloaded functions also apply to operators. For example: %ignore Complex::operator=; // Ignore = in class Complex %ignore *::operator=; // Ignore = in all classes %ignore operator=; // Ignore = everywhere. %rename(__sub__) Complex::operator-; %rename(__neg__) Complex::operator-(); // Unary -
The last part of this example illustrates how multiple definitions of the Handling operators in this manner is mostly straightforward. However, there are a few subtle issues to keep in mind:
public: friend Complex operator+(Complex &, double);
};
Complex operator+(Complex &, double);
SWIG simply ignores all
6.17 Class extension
New methods can be added to a class using the %module vector %{ #include "vector.h" %} class Vector { public: double x,y,z; Vector(); ~Vector(); ... bunch of C++ methods ... %extend { char *__str__() { static char temp[256]; sprintf(temp,"[ %g, %g, %g ]", $self->x,$self->y,$self->z); return &temp[0]; } } };
This code adds a >>> >>> v = Vector(); >>> v.x = 3 >>> v.y = 4 >>> v.z = 0 >>> print(v) [ 3.0, 4.0, 0.0 ] >>>
The C++ 'this' pointer is often needed to access member variables, methods etc. The struct Base { virtual void method(int v) { ... } int value; }; struct Derived : Base { }; %extend Derived { virtual void method(int v) { $self->Base::method(v); // akin to this->Base::method(v); $self->value = v; // akin to this->value = v; ... } }
The
Compatibility note: The 6.18 TemplatesTemplate type names may appear anywhere a type is expected in an interface file. For example: void foo(vector<int> *a, int n); void bar(list<int,100> *x); There are some restrictions on the use of non-type arguments. Simple literals are supported, and so are some constant expressions. However, use of '<' and '>' within a constant expressions currently is not supported by SWIG ('⇐' and '>=' are though). For example: void bar(list<int,100> *x); // OK void bar(list<int,2*50> *x); // OK void bar(list<int,(2>1 ? 100 : 50)> *x) // Not supported
The type system is smart enough to figure out clever games you might try to play with typedef int Integer; void foo(vector<int> *x, vector<Integer> *y);
In this case,
Starting with SWIG-1.3.7, simple C++ template declarations can also be wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. Before discussing this any further, there are a few things you need to know about template wrapping. First, a bare C++ template does not define any sort of runnable object-code for which SWIG can normally create a wrapper. Therefore, in order to wrap a template, you need to give SWIG information about a particular template instantiation (e.g., To illustrate, consider the following template definition: template<class T> class List { private: T *data; int nitems; int maxitems; public: List(int max) { data = new T [max]; nitems = 0; maxitems = max; } ~List() { delete [] data; }; void append(T obj) { if (nitems < maxitems) { data[nitems++] = obj; } } int length() { return nitems; } T get(int n) { return data[n]; } };
By itself, this template declaration is useless–SWIG simply ignores it because it doesn't know how to generate any code until unless a definition of One way to create wrappers for a specific template instantiation is to simply provide an expanded version of the class directly like this: %rename(intList) List<int>; // Rename to a suitable identifier class List<int> { private: int *data; int nitems; int maxitems; public: List(int max); ~List(); void append(int obj); int length(); int get(int n); };
The
Since manual expansion of templates gets old in a hurry, the /* Instantiate a few different versions of the template */ %template(intList) List<int>; %template(doubleList) List<double>;
The argument to %template(intList) List<int>; ... typedef List<int> intList; // OK SWIG can also generate wrappers for function templates using a similar technique. For example: // Function template template<class T> T max(T a, T b) { return a > b ? a : b; } // Make some different versions of this function %template(maxint) max<int>; %template(maxdouble) max<double>;
In this case,
The number of arguments supplied to template vector<typename T, int max=100> class vector { ... }; %template(intvec) vector<int>; // OK %template(vec1000) vector<int,1000>; // OK
The %template(intList) List<int>; %template(Listint) List<int>; // Error. Template already wrapped. This error is caused because the template expansion results in two identical classes with the same name. This generates a symbol table conflict. Besides, it probably more efficient to only wrap a specific instantiation only once in order to reduce the potential for code bloat.
Since the type system knows how to handle %template(intList) vector<int>; typedef int Integer; ... void foo(vector<Integer> *x);
In this case,
When a template is instantiated using ... %template(intList) List<int>; ... class UltraList : public List<int> { ... };
then SWIG knows that example.h:42. Nothing known about class 'List<int >' (ignored). example.h:42. Maybe you forgot to instantiate 'List<int >' using %template. If a template class inherits from another template class, you need to make sure that base classes are instantiated before derived classes. For example: template<class T> class Foo { ... }; template<class T> class Bar : public Foo<T> { ... }; // Instantiate base classes first %template(intFoo) Foo<int>; %template(doubleFoo) Foo<double>; // Now instantiate derived classes %template(intBar) Bar<int>; %template(doubleBar) Bar<double>; The order is important since SWIG uses the instantiation names to properly set up the inheritance hierarchy in the resulting wrapper code (and base classes need to be wrapped before derived classes). Don't worry–if you get the order wrong, SWIG should generate a warning message.
Occasionally, you may need to tell SWIG about base classes that are defined by templates, but which aren't supposed to be wrapped. Since SWIG is not able to automatically instantiate templates for this purpose, you must do it manually. To do this, simply use // Instantiate traits<double,double>, but don't wrap it. %template() traits<double,double>; If you have to instantiate a lot of different classes for many different types, you might consider writing a SWIG macro. For example: %define TEMPLATE_WRAP(prefix, T...) %template(prefix ## Foo) Foo<T >; %template(prefix ## Bar) Bar<T >; ... %enddef TEMPLATE_WRAP(int, int) TEMPLATE_WRAP(double, double) TEMPLATE_WRAP(String, char *) TEMPLATE_WRAP(PairStringInt, std::pair<string, int>) ... Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible. The SWIG template mechanism does support specialization. For instance, if you define a class like this, template<> class List<int> { private: int *data; int nitems; int maxitems; public: List(int max); ~List(); void append(int obj); int length(); int get(int n); };
then SWIG will use this code whenever the user expands Partial template specialization is partially supported by SWIG. For example, this code defines a template that is applied when the template argument is a pointer. template<class T> class List<T*> { private: T *data; int nitems; int maxitems; public: List(int max); ~List(); void append(int obj); int length(); T get(int n); }; SWIG should be able to handle most simple uses of partial specialization. However, it may fail to match templates properly in more complicated cases. For example, if you have this code, template<class T1, class T2> class Foo<T1, T2 *> { };
SWIG isn't able to match it properly for instantiations like Member function templates are supported. The underlying principle is the same as for normal templates–SWIG can't create a wrapper unless you provide more information about types. For example, a class with a member template might look like this: class Foo { public: template<class T> void bar(T x, T y) { ... }; ... };
To expand the template, simply use class Foo { public: template<class T> void bar(T x, T y) { ... }; ... %template(barint) bar<int>; %template(bardouble) bar<double>; }; Or, if you want to leave the original class definition alone, just do this: class Foo { public: template<class T> void bar(T x, T y) { ... }; ... }; ... %extend Foo { %template(barint) bar<int>; %template(bardouble) bar<double>; }; or simply class Foo { public: template<class T> void bar(T x, T y) { ... }; ... }; ... %template(bari) Foo::bar<int>; %template(bard) Foo::bar<double>;
In this case, the
Note: because of the way that templates are handled, the Now, if your target language supports overloading, you can even try %template(bar) Foo::bar<int>; %template(bar) Foo::bar<double>; and since the two new wrapped methods have the same name 'bar', they will be overloaded, and when called, the correct method will be dispatched depending on the argument type.
When used with members, the // A template template<class T> class Foo { public: // A member template template<class S> T bar(S x, S y) { ... }; ... }; // Expand a few member templates %extend Foo { %template(bari) bar<int>; %template(bard) bar<double>; } // Create some wrappers for the template %template(Fooi) Foo<int>; %template(Food) Foo<double>;
Miraculously, you will find that each expansion of A common use of member templates is to define constructors for copies and conversions. For example: template<class T1, class T2> struct pair { T1 first; T2 second; pair() : first(T1()), second(T2()) { } pair(const T1 &x, const T2 &y) : first(x), second(y) { } template<class U1, class U2> pair(const pair<U1,U2> &x) : first(x.first),second(x.second) { } }; This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored unless you explicitly expand it. To do that, you could expand a few versions of the constructor in the template class itself. For example: %extend pair { %template(pair) pair<T1,T2>; // Generate default copy constructor };
When using Alternatively, you could expand the constructor template in selected instantiations. For example: // Instantiate a few versions %template(pairii) pair<int,int>; %template(pairdd) pair<double,double>; // Create a default constructor only %extend pair<int,int> { %template(paird) pair<int,int>; // Default constructor }; // Create default and conversion constructors %extend pair<double,double> { %template(paird) pair<double,dobule>; // Default constructor %template(pairc) pair<int,int>; // Conversion constructor }; And if your target language supports overloading, then you can try instead: // Create default and conversion constructors %extend pair<double,double> { %template(pair) pair<double,dobule>; // Default constructor %template(pair) pair<int,int>; // Conversion constructor }; In this case, the default and conversion constructors have the same name. Hence, Swig will overload them and define an unique visible constructor, that will dispatch the proper call depending on the argument type.
If all of this isn't quite enough and you really want to make someone's head explode, SWIG directives such as // File : list.h template<class T> class List { ... public: %rename(__getitem__) get(int); List(int max); ~List(); ... T get(int index); %extend { char *__str__() { /* Make a string representation */ ... } } }; In this example, the extra SWIG directives are propagated to every template instantiation. It is also possible to separate these declarations from the template class. For example: %rename(__getitem__) List::get; %extend List { char *__str__() { /* Make a string representation */ ... } /* Make a copy */ T *__copy__() { return new List<T>(*$self); } }; ... template<class T> class List { ... public: List() { }; T get(int index); ... };
When %template(intList) List<int>; %extend List<int> { void blah() { printf("Hey, I'm an List<int>!\n"); } };
SWIG even supports overloaded templated functions. As usual the template<class T> void foo(T x) { }; template<class T> void foo(T x, T y) { }; %template(foo) foo<int>; This will generate two overloaded wrapper methods, the first will take a single integer as an argument and the second will take two integer arguments. Needless to say, SWIG's template support provides plenty of opportunities to break the universe. That said, an important final point is that SWIG does not perform extensive error checking of templates! Specifically, SWIG does not perform type checking nor does it check to see if the actual contents of the template declaration make any sense. Since the C++ compiler will hopefully check this when it compiles the resulting wrapper file, there is no practical reason for SWIG to duplicate this functionality (besides, none of the SWIG developers are masochistic enough to want to implement this right now). Compatibility Note: The first implementation of template support relied heavily on macro expansion in the preprocessor. Templates have been more tightly integrated into the parser and type system in SWIG-1.3.12 and the preprocessor is no longer used. Code that relied on preprocessing features in template expansion will no longer work. However, SWIG still allows the # operator to be used to generate a string from a template argument.
Compatibility Note: In earlier versions of SWIG, the %template(vectori) vector<int>; %extend vectori { void somemethod() { } }; This behavior is no longer supported. Instead, you should use the original template name as the class name. For example: %template(vectori) vector<int>; %extend vector<int> { void somemethod() { } }; Similar changes apply to typemaps and other customization features. 6.19 NamespacesSupport for C++ namespaces is a relatively late addition to SWIG, first appearing in SWIG-1.3.12. Before describing the implementation, it is worth noting that the semantics of C++ namespaces is extremely non-trivial–especially with regard to the C++ type system and class machinery. At a most basic level, namespaces are sometimes used to encapsulate common functionality. For example: namespace math { double sin(double); double cos(double); class Complex { double im,re; public: ... }; ... }; Members of the namespace are accessed in C++ by prepending the namespace prefix to names. For example: double x = math::sin(1.0); double magnitude(math::Complex *c); math::Complex c; ...
At this level, namespaces are relatively easy to manage. However, things start to get very ugly when you throw in the other ways a namespace can be used. For example, selective symbols can be exported from a namespace with using math::Complex; double magnitude(Complex *c); // Namespace prefix stripped Similarly, the contents of an entire namespace can be made available like this: using namespace math; double x = sin(1.0); double magnitude(Complex *c); Alternatively, a namespace can be aliased: namespace M = math; double x = M::sin(1.0); double magnitude(M::Complex *c); Using combinations of these features, it is possible to write head-exploding code like this: namespace A { class Foo { }; } namespace B { namespace C { using namespace A; } typedef C::Foo FooClass; } namespace BIGB = B; namespace D { using BIGB::FooClass; class Bar : public FooClass { } }; class Spam : public D::Bar { }; void evil(A::Foo *a, B::FooClass *b, B::C::Foo *c, BIGB::FooClass *d, BIGB::C::Foo *e, D::FooClass *f); Given the possibility for such perversion, it's hard to imagine how every C++ programmer might want such code wrapped into the target language. Clearly this code defines three different classes. However, one of those classes is accessible under at least six different names! SWIG fully supports C++ namespaces in its internal type system and class handling code. If you feed SWIG the above code, it will be parsed correctly, it will generate compilable wrapper code, and it will produce a working scripting language module. However, the default wrapping behavior is to flatten namespaces in the target language. This means that the contents of all namespaces are merged together in the resulting scripting language module. For example, if you have code like this, %module foo namespace foo { void bar(int); void spam(); } namespace bar { void blah(); }
then SWIG simply creates three wrapper functions There is some rationale for taking this approach. Since C++ namespaces are often used to define modules in C++, there is a natural correlation between the likely contents of a SWIG module and the contents of a namespace. For instance, it would not be unreasonable to assume that a programmer might make a separate extension module for each C++ namespace. In this case, it would be redundant to prepend everything with an additional namespace prefix when the module itself already serves as a namespace in the target language. Or put another way, if you want SWIG to keep namespaces separate, simply wrap each namespace with its own SWIG interface. Because namespaces are flattened, it is possible for symbols defined in different namespaces to generate a name conflict in the target language. For example: namespace A { void foo(int); } namespace B { void foo(double); } When this conflict occurs, you will get an error message that resembles this: example.i:26. Error. 'foo' is multiply defined in the generated module. example.i:23. Previous declaration of 'foo'
To resolve this error, simply use %rename(B_foo) B::foo; ... namespace A { void foo(int); } namespace B { void foo(double); // Gets renamed to B_foo }
Similarly,
namespace A { typedef int Integer; } using namespace A; void foo(Integer x);
SWIG knows that
Namespaces may be combined with templates. If necessary, the namespace foo { template<typename T> T max(T a, T b) { return a > b ? a : b; } } using foo::max; %template(maxint) max<int>; // Okay. %template(maxfloat) foo::max<float>; // Okay (qualified name). namespace bar { using namespace foo; %template(maxdouble) max<double>; // Okay. }
The combination of namespaces and other SWIG directives may introduce subtle scope-related problems. The key thing to keep in mind is that all SWIG generated wrappers are produced in the global namespace. Symbols from other namespaces are always accessed using fully qualified names—names are never imported into the global space unless the interface happens to do so with a namespace foo { typedef int Integer; class bar { public: ... }; } %extend foo::bar { Integer add(Integer x, Integer y) { Integer r = x + y; // Error. Integer not defined in this scope return r; } };
In this case, SWIG correctly resolves the added method parameters and return type to %extend foo::bar { Integer add(Integer x, Integer y) { foo::Integer r = x + y; // Ok. return r; } };
Note: SWIG does not propagate
Note: Code inclusion directives such as // Good version %inline %{ namespace foo { void bar(int) { ... } ... } %} // Bad version. Emitted code not placed in namespace. namespace foo { %inline %{ void bar(int) { ... } /* I'm bad */ ... %} }
Note: When the namespace foo { class bar { public: %extend { int blah(int x); }; }; }
the added method Note: Although namespaces are flattened in the target language, the SWIG generated wrapper code observes the same namespace conventions as used in the input file. Thus, if there are no symbol conflicts in the input, there will be no conflicts in the generated code. Note: In the same way that no resolution is performed on parameters, a conversion operator name must match exactly to how it is defined. Do not change the qualification of the operator. For example, suppose you had an interface like this: namespace foo { class bar; class spam { public: ... operator bar(); // Conversion of spam -> bar ... }; } The following is how the feature is expected to be written for a successful match: %rename(tofoo) foo::spam::operator bar(); The following does not work as no namespace resolution is performed in the matching of conversion operator names: %rename(tofoo) foo::spam::operator foo::bar(); Note, however, that if the operator is defined using a qualifier in its name, then the feature must use it too… %rename(tofoo) foo::spam::operator bar(); // will not match %rename(tofoo) foo::spam::operator foo::bar(); // will match namespace foo { class bar; class spam { public: ... operator foo::bar(); ... }; } Compatibility Note: Versions of SWIG prior to 1.3.32 were inconsistent in this approach. A fully qualified name was usually required, but would not work in some situations. Note: The flattening of namespaces is only intended to serve as a basic namespace implementation. None of the target language modules are currently programmed with any namespace awareness. In the future, language modules may or may not provide more advanced namespace support. 6.20 Renaming templated types in namespaces
As has been mentioned, when %rename includes parameters, the parameter types must match exactly (no typedef or namespace resolution is performed). SWIG treats templated types slightly differently and has an additional matching rule so unlike non-templated types, an exact match is not always required. If the fully qualified templated type is specified, it will have a higher precedence over the generic template type. In the example below, the generic template type is used to rename to %rename(bbb) Space::ABC::aaa(T t); // will match but with lower precedence than ccc %rename(ccc) Space::ABC<Space::XYZ>::aaa(Space::XYZ t); // will match but with higher precedence than bbb namespace Space { class XYZ {}; template<typename T> struct ABC { void aaa(T t) {} }; } %template(ABCXYZ) Space::ABC<Space::XYZ>; It should now be apparent that there are many ways to achieve a renaming with %rename. This is demonstrated by the following two examples, which are effectively the same as the above example. Below shows how %rename can be placed inside a namespace. namespace Space { %rename(bbb) ABC::aaa(T t); // will match but with lower precedence than ccc %rename(ccc) ABC<Space::XYZ>::aaa(Space::XYZ t); // will match but with higher precedence than bbb %rename(ddd) ABC<Space::XYZ>::aaa(XYZ t); // will not match } namespace Space { class XYZ {}; template<typename T> struct ABC { void aaa(T t) {} }; } %template(ABCXYZ) Space::ABC<Space::XYZ>;
Note that namespace Space { %extend ABC { %rename(bbb) aaa(T t); // will match but with lower precedence than ccc } %extend ABC<Space::XYZ> { %rename(ccc) aaa(Space::XYZ t); // will match but with higher precedence than bbb %rename(ddd) aaa(XYZ t); // will not match } } namespace Space { class XYZ {}; template<typename T> struct ABC { void aaa(T t) {} }; } %template(ABCXYZ) Space::ABC<Space::XYZ>; 6.21 Exception specificationsWhen C++ programs utilize exceptions, exceptional behavior is sometimes specified as part of a function or method declaration. For example: class Error { }; class Foo { public: ... void blah() throw(Error); ... }; If an exception specification is used, SWIG automatically generates wrapper code for catching the indicated exception and, when possible, rethrowing it into the target language, or converting it into an error in the target language otherwise. For example, in Python, you can write code like this: f = Foo() try: f.blah() except Error,e: # e is a wrapped instance of "Error" Details of how to tailor code for handling the caught C++ exception and converting it into the target language's exception/error handling mechanism is outlined in the "throws" typemap section. Since exception specifications are sometimes only used sparingly, this alone may not be enough to properly handle C++ exceptions. To do that, a different set of special SWIG directives are used. Consult the “Exception handling with %exception” section for details. The next section details a way of simulating an exception specification or replacing an existing one. 6.22 Exception handling with %catches
Exceptions are automatically handled for methods with an exception specification. Similar handling can be achieved for methods without exception specifications through the struct EBase { virtual ~EBase(); }; struct Error1 : EBase { }; struct Error2 : EBase { }; struct Error3 : EBase { }; struct Error4 : EBase { }; %catches(Error1,Error2,...) Foo::bar(); %catches(EBase) Foo::blah(); class Foo { public: ... void bar(); void blah() throw(Error1,Error2,Error3,Error4); ... };
For the
Without the 6.23 Pointers to MembersStarting with SWIG-1.3.7, there is limited parsing support for pointers to C++ class members. For example: double do_op(Object *o, double (Object::*callback)(double,double)); extern double (Object::*fooptr)(double,double); %constant double (Object::*FOO)(double,double) = &Object::foo; Although these kinds of pointers can be parsed and represented by the SWIG type system, few language modules know how to handle them due to implementation differences from standard C pointers. Readers are strongly advised to consult an advanced text such as the “The Annotated C++ Manual” for specific details. When pointers to members are supported, the pointer value might appear as a special string like this: >>> print example.FOO _ff0d54a800000000_m_Object__f_double_double__double >>> In this case, the hexadecimal digits represent the entire value of the pointer which is usually the contents of a small C++ structure on most machines. SWIG's type-checking mechanism is also more limited when working with member pointers. Normally SWIG tries to keep track of inheritance when checking types. However, no such support is currently provided for member pointers. 6.24 Smart pointers and operator->()
In some C++ programs, objects are often encapsulated by smart-pointers or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or persistence. Typically a smart-pointer is defined by a template class where the // Smart-pointer class template<class T> class SmartPtr { T *pointee; public: ... T *operator->() { return pointee; } ... }; // Ordinary class class Foo_Impl { public: int x; virtual void bar(); ... }; // Smart-pointer wrapper typedef SmartPtr<Foo_Impl> Foo; // Create smart pointer Foo Foo make_Foo() { return SmartPtr(new Foo_Impl()); } // Do something with smart pointer Foo void do_something(Foo f) { printf("x = %d\n", f->x); f->bar(); }
A key feature of this approach is that by defining f->x f->bar() are transparently mapped to the following (f.operator->())->x; (f.operator->())->bar();
When generating wrappers, SWIG tries to emulate this functionality to the extent that it is possible. To do this, whenever int Foo_x_get(Foo *f) { return (*f)->x; } void Foo_x_set(Foo *f, int value) { (*f)->x = value; } void Foo_bar(Foo *f) { (*f)->bar(); }
These wrappers take a smart-pointer instance as an argument, but dereference it in a way to gain access to the object returned by The end result is that access looks very similar to C++. For example, you could do this in Python: >>> f = make_Foo() >>> print f.x 0 >>> f.bar() >>>
When generating wrappers through a smart-pointer, SWIG tries to generate wrappers for all methods and attributes that might be accessible through
public: int x; }; class Bar { public: int x; Foo *operator->();
};
then the wrapper for If your intent is to only expose the smart-pointer class in the interface, it is not necessary to wrap both the smart-pointer class and the class for the underlying object. However, you must still tell SWIG about both classes if you want the technique described in this section to work. To only generate wrappers for the smart-pointer class, you can use the %ignore directive. For example: %ignore Foo; class Foo { // Ignored }; class Bar { public: Foo *operator->(); ... };
Alternatively, you can import the definition of
Note: When a class defines f = Foo() # Smart-pointer p = f.__deref__() # Raw pointer from operator->
Note: To disable the smart-pointer behavior, use %ignore Bar::operator->; Note: Smart pointer support was first added in SWIG-1.3.14. 6.25 Using declarations and inheritance
class Foo { public: int blah(int x); }; class Bar { public: double blah(double x); }; class FooBar : public Foo, public Bar { public: using Foo::blah; using Bar::blah; char *blah(const char *x); };
In this example, the FooBar *f; f->blah(3); // Ok. Invokes Foo::blah(int) f->blah(3.5); // Ok. Invokes Bar::blah(double) f->blah("hello"); // Ok. Invokes FooBar::blah(const char *); SWIG emulates the same functionality when creating wrappers. For example, if you wrap this code in Python, the module works just like you would expect: >>> import example >>> f = example.FooBar() >>> f.blah(3) >>> f.blah(3.5) >>> f.blah("hello")
class Foo { protected: int x; int blah(int x); }; class Bar : public Foo { public: using Foo::x; // Make x public using Foo::blah; // Make blah public }; This also works in SWIG—the exposed declarations will be wrapped normally.
When
Because a class FooBar : public Foo, public Bar { public: #ifndef SWIG using Foo::blah; using Bar::blah; #else int blah(int x); // explicitly tell SWIG about other declarations double blah(double x); #endif char *blah(const char *x); }; Notes:
public: int blah(int ); double blah(double); }; class Bar : public Foo { public: using Foo::blah; %%//%% Only imports blah(double); int blah(int); };
class Foo { public: int blah(int); long blah(long); %%//%% Renamed to blah_long }; class Bar : public Foo { public: using Foo::blah; %%//%% Only imports blah(int) double blah(double x); }; 6.26 Nested classesThere is limited support for nested structs and unions when wrapping C code, see Nested structures for further details. However, there is no nested class/struct/union support when wrapping C++ code (using the -c++ commandline option). This may be added at a future date, however, until then some of the following workarounds can be applied. It might be possible to use partial class information. Since SWIG does not need the entire class specification to work, conditional compilation can be used to comment out the problematic nested class definition, you might do this: class Foo { public: #ifndef SWIG class Bar { public: ... }; #endif Foo(); ~Foo(); ... };
The next workaround assumes you cannot modify the source code as was done above and it provides a solution for methods that use nested class types. Imagine we are wrapping the // File outer.h class Outer { public: class Inner { public: int var; Inner(int v = 0) : var(v) {} }; void method(Inner inner); }; The following interface file works around SWIG nested class limitations by redefining the nested class as a global class. A typedef for the compiler is also required in order for the generated wrappers to compile. // File : example.i %module example // Suppress SWIG warning #pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS // Redefine nested class in global scope in order for SWIG to generate // a proxy class. Only SWIG parses this definition. class Inner { public: int var; Inner(int v = 0) : var(v) {} }; %{ #include "outer.h" %} %include "outer.h" %{ // SWIG thinks that Inner is a global class, so we need to trick the C++ // compiler into understanding this so called global type. typedef Outer::Inner Inner; %}
The downside to this approach is having to maintain two definitions of 6.27 A brief rant about const-correctness
A common issue when working with C++ programs is dealing with all possible ways in which the
Although SWIG knows how to correctly deal with const Object * foo(); void bar(Object *); ... // C++ code void blah() { bar(foo()); // Error: bar discards const }; Now, consider the behavior when wrapped into a Python module: >>> bar(foo()) # Okay >>> Although this is clearly a violation of the C++ type-system, fixing the problem doesn't seem to be worth the added implementation complexity that would be required to support it in the SWIG run-time type system. There are no plans to change this in future releases (although we'll never rule anything out entirely). The bottom line is that this particular issue does not appear to be a problem for most SWIG projects. Of course, you might want to consider using another tool if maintaining constness is the most important part of your project. 6.28 Where to go for more informationIf you're wrapping serious C++ code, you might want to pick up a copy of “The Annotated C++ Reference Manual” by Ellis and Stroustrup. This is the reference document we use to guide a lot of SWIG's C++ support. 7 PreprocessingSWIG includes its own enhanced version of the C preprocessor. The preprocessor supports the standard preprocessor directives and macro expansion rules. However, a number of modifications and enhancements have been made. This chapter describes some of these modifications. 7.1 File inclusion
To include another file into a SWIG interface, use the %include "pointer.i"
Unlike,
By default, the 7.2 File imports
SWIG provides another file inclusion directive with the %import "foo.i"
The purpose of
The 7.3 Conditional Compilation
SWIG fully supports the use of SWIG Always defined when SWIG is processing a file SWIGIMPORTED Defined when SWIG is importing a file with %import SWIGMAC Defined when running SWIG on the Macintosh SWIGWIN Defined when running SWIG under Windows SWIG_VERSION Hexadecimal number containing SWIG version, such as 0x010311 (corresponding to SWIG-1.3.11). SWIGALLEGROCL Defined when using Allegro CL SWIGCFFI Defined when using CFFI SWIGCHICKEN Defined when using CHICKEN SWIGCLISP Defined when using CLISP SWIGCSHARP Defined when using C# SWIGGUILE Defined when using Guile SWIGJAVA Defined when using Java SWIGLUA Defined when using Lua SWIGMODULA3 Defined when using Modula-3 SWIGMZSCHEME Defined when using Mzscheme SWIGOCAML Defined when using Ocaml SWIGOCTAVE Defined when using Octave SWIGPERL Defined when using Perl SWIGPHP Defined when using PHP SWIGPIKE Defined when using Pike SWIGPYTHON Defined when using Python SWIGR Defined when using R SWIGRUBY Defined when using Ruby SWIGSEXP Defined when using S-expressions SWIGTCL Defined when using Tcl SWIGXML Defined when using XML In addition, SWIG defines the following set of standard C/C++ macros: __LINE__ Current line number __FILE__ Current file name __STDC__ Defined to indicate ANSI C __cplusplus Defined when -c++ option used
Interface files can look at these symbols as necessary to change the way in which an interface is generated or to mix SWIG directives with C code. These symbols are also defined within the C code generated by SWIG (except for the symbol ` 7.4 Macro Expansion
Traditional preprocessor macros can be used in SWIG interfaces. Be aware that the #ifndef _FOO_H 1 #define _FOO_H 1 ... #endif
you may get some extra constants such as More complex macros can be defined in the standard way. For example: #define EXTERN extern #ifdef __STDC__ #define _ANSI(args) (args) #else #define _ANSI(args) () #endif The following operators can appear in macro definitions:
7.5 SWIG Macros
SWIG provides an enhanced macro capability with the %define ARRAYHELPER(type,name) %inline %{ type *new_ ## name (int nitems) { return (type *) malloc(sizeof(type)*nitems); } void delete_ ## name(type *t) { free(t); } type name ## _get(type *t, int index) { return t[index]; } void name ## _set(type *t, int index, type val) { t[index] = val; } %} %enddef ARRAYHELPER(int, IntArray) ARRAYHELPER(double, DoubleArray)
The primary purpose of The SWIG macro capability is a very quick and easy way to generate large amounts of code. In fact, many of SWIG's advanced features and libraries are built using this mechanism (such as C++ template support). 7.6 C99 and GNU ExtensionsSWIG-1.3.12 and newer releases support variadic preprocessor macros. For example: #define DEBUGF(fmt,...) fprintf(stderr,fmt,__VA_ARGS__)
When used, any extra arguments to SWIG allows a variable number of arguments to be empty. However, this often results in an extra comma (,) and syntax error in the resulting expansion. For example: DEBUGF("hello"); --> fprintf(stderr,"hello",);
To get rid of the extra comma, use #define DEBUGF(fmt,...) fprintf(stderr,fmt, ##__VA_ARGS__) SWIG also supports GNU-style variadic macros. For example: #define DEBUGF(fmt, args...) fprintf(stdout,fmt,args) Comment: It's not entirely clear how variadic macros might be useful to interface building. However, they are used internally to implement a number of SWIG directives and are provided to make SWIG more compatible with C99 code. 7.7 Preprocessing and %{ ... %} & " ... " delimitersThe SWIG preprocessor does not process any text enclosed in a code block %{ … %}. Therefore, if you write code like this, %{ #ifdef NEED_BLAH int blah() { ... } #endif %}
the contents of the 7.8 Preprocessing and { ... } delimiters
SWIG always runs the preprocessor on text appearing inside %extend Foo { void bar() { #ifdef DEBUG printf("I'm in bar\n"); #endif } }
By default, SWIG will interpret the %extend Foo { void bar() { %#ifdef DEBUG printf("I'm in bar\n"); %#endif } }
SWIG will strip the extra 7.9 Preprocessor and Typemaps
Typemaps support a special attribute called #define SWIG_macro(CAST) (CAST)$input %typemap(in) Int {$1= SWIG_macro(int);} might generate { arg1=(int)jarg1; } whereas #define SWIG_macro(CAST) (CAST)$input %typemap(in,noblock=1) Int {$1= SWIG_macro(int);} might generate arg1=(int)jarg1; and #define SWIG_macro(CAST) (CAST)$input %typemap(in) Int %{$1=SWIG_macro(int);%} would generate arg1=SWIG_macro(int); 7.10 Viewing preprocessor output
Like many compilers, SWIG supports a 7.11 The #error and #warning directives
SWIG supports the commonly used #error "This is a fatal error message" #warning "This is a warning message"
The /* Modified behaviour: #error does not cause SWIG to exit with error */ #pragma SWIG cpperraswarn=1 /* Normal behaviour: #error does cause SWIG to exit with error */ #pragma SWIG cpperraswarn=0 8 SWIG libraryTo help build extension modules, SWIG is packaged with a library of support files that you can include in your own interfaces. These files often define new SWIG directives or provide utility functions that can be used to access parts of the standard C and C++ libraries. This chapter provides a reference to the current set of supported library files. Compatibility note: Older versions of SWIG included a number of library files for manipulating pointers, arrays, and other structures. Most these files are now deprecated and have been removed from the distribution. Alternative libraries provide similar functionality. Please read this chapter carefully if you used the old libraries. 8.1 The %include directive and library search path
Library files are included using the
Within each directory, SWIG first looks for a subdirectory corresponding to a target language (e.g.,
You can ignore the installed SWIG library by setting the
The directories that are searched are displayed when using 8.2 C Arrays and Pointers
This section describes library modules for manipulating low-level C arrays and pointers. The primary use of these modules is in supporting C declarations that manipulate bare pointers such as 8.2.1 cpointer.i
The
Generates a collection of four functions for manipulating a pointer
Creates a new object of type
Creates a new object of type
Deletes an object type
Assigns
Returns the value of
When using this macro,
Here is a simple example of using %module example %include "cpointer.i" /* Create some functions for working with "int *" */ %pointer_functions(int, intp); /* A function that uses an "int *" */ void add(int x, int y, int *result); Now, in Python: >>> import example >>> c = example.new_intp() # Create an "int" for storing result >>> example.add(3,4,c) # Call function >>> example.intp_value(c) # Dereference 7 >>> example.delete_intp(c) # Delete
Wraps a pointer of struct name { name(); // Create pointer object ~name(); // Delete pointer object void assign(type value); // Assign value type value(); // Get value type *cast(); // Cast the pointer to original type static name *frompointer(type *); // Create class wrapper from existing // pointer };
When using this macro,
If the target language does not support proxy classes, the use of this macro will produce the example same functions as It should be noted that the class interface does introduce a new object or wrap a pointer inside a special structure. Instead, the raw pointer is used directly. Here is the same example using a class instead: %module example %include "cpointer.i" /* Wrap a class interface around an "int *" */ %pointer_class(int, intp); /* A function that uses an "int *" */ void add(int x, int y, int *result); Now, in Python (using proxy classes) >>> import example >>> c = example.intp() # Create an "int" for storing result >>> example.add(3,4,c) # Call function >>> c.value() # Dereference 7
Of the two macros,
Creates a casting function that converts %pointer_cast(int *, unsigned int *, int_to_uint);
In this example, the function
Note: None of these macros can be used to safely work with strings ( Note: When working with simple pointers, typemaps can often be used to provide more seamless operation. 8.2.2 carrays.iThis module defines macros that assist in wrapping ordinary C pointers as arrays. The module does not provide any safety or an extra layer of wrapping–it merely provides functionality for creating, destroying, and modifying the contents of raw C array data.
Creates four functions.
Creates a new array of objects of type
Deletes an array. In C,
Returns the value
Assigns
When using this macro,
Here is an example of void print_array(double x[10]) { int i; for (i = 0; i < 10; i++) { printf("[%d] = %g\n", i, x[i]); } } To wrap it, you might write this: %module example %include "carrays.i" %array_functions(double, doubleArray); void print_array(double x[10]); Now, in a scripting language, you might write this: a = new_doubleArray(10) # Create an array for i in range(0,10): doubleArray_setitem(a,i,2*i) # Set a value print_array(a) # Pass to C delete_doubleArray(a) # Destroy array
Wraps a pointer of struct name { name(int nelements); // Create an array ~name(); // Delete array type getitem(int index); // Return item void setitem(int index, type value); // Set item type *cast(); // Cast to original type static name *frompointer(type *); // Create class wrapper from // existing pointer };
When using this macro,
When combined with proxy classes, the %module example %include "carrays.i" %array_class(double, doubleArray); void print_array(double x[10]); Allows you to do this: import example c = example.doubleArray(10) # Create double[10] for i in range(0,10): c[i] = 2*i # Assign values example.print_array(c) # Pass to C Note: These macros do not encapsulate C arrays inside a special data structure or proxy. There is no bounds checking or safety of any kind. If you want this, you should consider using a special array object rather than a bare pointer.
Note: 8.2.3 cmalloc.i
This module defines macros for wrapping the low-level C memory allocation functions
Creates a wrapper around type *malloc_name(int nbytes = sizeof(type));
If
Creates a wrapper around type *calloc_name(int nobj =1, int sz = sizeof(type));
If
Creates a wrapper around type *realloc_name(type *ptr, int nitems);
Note: unlike the C
Creates a wrapper around void free_name(type *ptr);
Creates the constant: %constant int sizeof_name = sizeof(type);
Generates wrappers for all five of the above operations. Here is a simple example that illustrates the use of these macros: // SWIG interface %module example %include "cmalloc.i" %malloc(int); %free(int); %malloc(int *, intp); %free(int *, intp); %allocators(double); Now, in a script: >>> from example import * >>> a = malloc_int() >>> a '_000efa70_p_int' >>> free_int(a) >>> b = malloc_intp() >>> b '_000efb20_p_p_int' >>> free_intp(b) >>> c = calloc_double(50) >>> c '_000fab98_p_double' >>> c = realloc_double(100000) >>> free_double(c) >>> print sizeof_double 8 >>> 8.2.4 cdata.i
The
Converts
Copies all of the string data in One use of these functions is packing and unpacking data from memory. Here is a short example: // SWIG interface %module example %include "carrays.i" %include "cdata.i" %array_class(int, intArray); Python example: >>> a = intArray(10) >>> for i in range(0,10): ... a[i] = i >>> b = cdata(a,40) >>> b '\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04 \x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t' >>> c = intArray(10) >>> memmove(c,b) >>> print c[4] 4 >>> Since the size of data is not always known, the following macro is also defined:
Generates the following function for extracting C data for a given type. char *cdata_name(type* ptr, int nitems)
Note: These functions provide direct access to memory and can be used to overwrite data. Clearly they are unsafe. 8.3 C String Handling
A common problem when working with C programs is dealing with functions that manipulate raw character data using
The problems (and perils) of using 8.3.1 Default string handlingSuppose you have a C function with this prototype: char *foo(char *s);
The default wrapping behavior for this function is to set % foo Hello
then
There are obvious problems with the default behavior. First, since a 8.3.2 Passing binary dataIf you have a function that expects binary data, int parity(char *str, int len, int initial);
you can wrap the parameters %apply (char *STRING, int LENGTH) { (char *str, int len) }; ... int parity(char *str, int len, int initial); Now, in the target language, you can use binary string data like this: >>> s = "H\x00\x15eg\x09\x20" >>> parity(s,0) In the wrapper function, the passed string will be expanded to a pointer and length parameter. 8.3.3 Using %newobject to release memoryIf you have a function that allocates memory like this, char *foo() { char *result = (char *) malloc(...); ... return result; } then the SWIG generated wrappers will have a memory leak–the returned data will be copied into a string object and the old contents ignored.
To fix the memory leak, use the %newobject foo; ... char *foo(); This will release the result. 8.3.4 cstring.i
The void get_path(char *s) { // Potential buffer overflow---uh, oh. sprintf(s,"%s/%s", base_directory, sub_directory); } ... // Somewhere else in the C program { char path[1024]; ... get_path(path); ... } (Off topic rant: If your program really has functions like this, you would be well-advised to replace them with safer alternatives involving bounds checking). The macros defined in this module all expand to various combinations of typemaps. Therefore, the same pattern matching rules and ideas apply. %cstring_bounded_output(parm, maxsize)
Turns parameter %cstring_bounded_output(char *path, 1024); ... void get_path(char *path); In the target language: >>> get_path() /home/beazley/packages/Foo/Bar >>>
Internally, the wrapper function allocates a small buffer (on the stack) of the requested size and passes it as the pointer value. Data stored in the buffer is then returned as a function return value. If the function already returns a value, then the return value and the output string are returned together (multiple return values). If more than %cstring_chunk_output(parm, chunksize)
Turns parameter %cstring_chunk_output(char *packet, PACKETSIZE); ... void get_packet(char *packet); In the target language: >>> get_packet() '\xa9Y:\xf6\xd7\xe1\x87\xdbH;y\x97\x7f\xd3\x99\x14V\xec\x06\xea\xa2\x88' >>>
This macro is essentially identical to %cstring_bounded_mutable(parm, maxsize)
Turns parameter %cstring_bounded_mutable(char *ustr, 1024); ... void make_upper(char *ustr); In the target language: >>> make_upper("hello world") 'HELLO WORLD' >>>
Internally, this macro is almost exactly the same as %cstring_mutable(parm [, expansion])
Turns parameter %cstring_mutable(char *ustr); ... void make_upper(char *ustr); %cstring_mutable(char *hstr, HEADER_SIZE); ... void attach_header(char *hstr); In the target language: >>> make_upper("hello world") 'HELLO WORLD' >>> attach_header("Hello world") 'header: Hello world' >>>
This macro differs from %cstring_output_maxsize(parm, maxparm)
This macro is used to handle bounded character output functions where both a %cstring_output_maxsize(char *path, int maxpath); ... void get_path(char *path, int maxpath); In the target language: >>> get_path(1024) '/home/beazley/Packages/Foo/Bar' >>> This macro provides a safer alternative for functions that need to write string data into a buffer. User supplied buffer size is used to dynamically allocate memory on heap. Results are placed into that buffer and returned as a string object. %cstring_output_withsize(parm, maxparm)
This macro is used to handle bounded character output functions where both a %cstring_output_withsize(char *data, int *maxdata); ... void get_data(char *data, int *maxdata); In the target language: >>> get_data(1024) 'x627388912' >>> get_data(1024) 'xyzzy' >>>
This macro is a somewhat more powerful version of %cstring_output_allocate(parm, release)
This macro is used to return strings that are allocated within the program and returned in a parameter of type void foo(char **s) { *s = (char *) malloc(64); sprintf(*s, "Hello world\n"); }
The returned string is assumed to be NULL-terminated. %cstring_output_allocate(char **s, free(*$1)); ... void foo(char **s); In the target language: >>> foo() 'Hello world\n' >>> %cstring_output_allocate_size(parm, szparm, release)
This macro is used to return strings that are allocated within the program and returned in two parameters of type void foo(char **s, int *sz) { *s = (char *) malloc(64); *sz = 64; // Write some binary data ... }
The returned string may contain binary data. %cstring_output_allocate_size(char **s, int *slen, free(*$1)); ... void foo(char **s, int *slen); In the target language: >>> foo() '\xa9Y:\xf6\xd7\xe1\x87\xdbH;y\x97\x7f\xd3\x99\x14V\xec\x06\xea\xa2\x88' >>> This is the safest and most reliable way to return binary string data in SWIG. If you have functions that conform to another prototype, you might consider wrapping them with a helper function. For example, if you had this: char *get_data(int *len); You could wrap it with a function like this: void my_get_data(char **result, int *len) { *result = get_data(len); } Comments:
8.4 STL/C++ LibraryThe library modules in this section provide access to parts of the standard C++ library including the STL. SWIG support for the STL is an ongoing effort. Support is quite comprehensive for some language modules but some of the lesser used modules do not have quite as much library code written. The following table shows which C++ classes are supported and the equivalent SWIG interface library file for the C++ library.
The list is by no means complete; some language modules support a subset of the above and some support additional STL classes. Please look for the library files in the appropriate language library directory. 8.4.1 std_string.i
The %module example %include "std_string.i" std::string foo(); void bar(const std::string &x); In the target language: x = foo(); # Returns a string object bar("Hello World"); # Pass string as std::string
A common problem that people encounter is that of classes/structures containing a %module example %include "std_string.i" %apply const std::string& {std::string* foo}; struct my_struct { std::string foo; }; In the target language: x = my_struct(); x.foo="Hello World"; # assign with string print x.foo; # print as string
This module only supports types
This library file is fully aware of C++ namespaces. If you export %module example %include "std_string.i" using namespace std; typedef std::string String; ... void foo(string s, const String &t); // std_string typemaps still applied
Note: The 8.4.2 std_vector.i
The %module example %include "std_vector.i" namespace std { %template(vectori) vector<int>; %template(vectord) vector<double>; };
When a template
To illustrate the use of this library, consider the following functions: /* File : example.h */ #include <vector> #include <algorithm> #include <functional> #include <numeric> double average(std::vector<int> v) { return std::accumulate(v.begin(),v.end(),0.0)/v.size(); } std::vector<double> half(const std::vector<double>& v) { std::vector<double> w(v); for (unsigned int i=0; i<w.size(); i++) w[i] /= 2.0; return w; } void halve_in_place(std::vector<double>& v) { std::transform(v.begin(),v.end(),v.begin(), std::bind2nd(std::divides<double>(),2.0)); } To wrap with SWIG, you might write the following: %module example %{ #include "example.h" %} %include "std_vector.i" // Instantiate templates used by example namespace std { %template(IntVector) vector<int>; %template(DoubleVector) vector<double>; } // Include the header file with above prototypes %include "example.h" Now, to illustrate the behavior in the scripting interpreter, consider this Python example: >>> from example import * >>> iv = IntVector(4) # Create an vector<int> >>> for i in range(0,4): ... iv[i] = i >>> average(iv) # Call method 1.5 >>> average([0,1,2,3]) # Call with list 1.5 >>> half([1,2,3]) # Half a list (0.5,1.0,1.5) >>> halve_in_place([1,2,3]) # Oops Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Type error. Expected _p_std__vectorTdouble_t >>> dv = DoubleVector(4) >>> for i in range(0,4): ... dv[i] = i >>> halve_in_place(dv) # Ok >>> for i in dv: ... print i ... 0.0 0.5 1.0 1.5 >>> dv[20] = 4.5 Traceback (most recent call last): File "<stdin>", line 1, in ? File "example.py", line 81, in __setitem__ def __setitem__(*args): return apply(examplec.DoubleVector___setitem__,args) IndexError: vector index out of range >>>
This library module is fully aware of C++ namespaces. If you use vectors with other names, make sure you include the appropriate %include "std_vector.i" namespace std { %template(IntVector) vector<int>; } using namespace std; typedef std::vector Vector; void foo(vector<int> *x, const Vector &x);
Note: This module makes use of several advanced SWIG features including templatized typemaps and template partial specialization. If you are trying to wrap other C++ code with templates, you might look at the code contained in Note: This module is defined for all SWIG target languages. However argument conversion details and the public API exposed to the interpreter vary.
Note: 8.4.3 STL exceptionsMany of the STL wrapper functions add parameter checking and will throw a language dependent error/exception should the values not be valid. The classic example is array bounds checking. The library wrappers are written to throw a C++ exception in the case of error. The C++ exception in turn gets converted into an appropriate error/exception for the target language. By and large this handling should not need customising, however, customisation can easily be achieved by supplying appropriate “throws” typemaps. For example: %module example %include "std_vector.i" %typemap(throws) std::out_of_range { // custom exception handler } %template(VectInt) std::vector<int>; The custom exception handler might, for example, log the exception then convert it into a specific error/exception for the target language.
When using the STL it is advisable to add in an exception handler to catch all STL exceptions. The %include "exception.i" %exception { try { $action } catch (const std::exception& e) { SWIG_exception(SWIG_RuntimeError, e.what()); } } Any thrown STL exceptions will then be gracefully handled instead of causing a crash. 8.5 Utility Libraries8.5.1 exception.i
The
Raises an exception in the target language. SWIG_MemoryError SWIG_IOError SWIG_RuntimeError SWIG_IndexError SWIG_TypeError SWIG_DivisionByZero SWIG_OverflowError SWIG_SyntaxError SWIG_ValueError SWIG_SystemError
The primary use of this module is in writing language-independent exception handlers. For example: %include "exception.i" %exception std::vector::getitem { try { $action } catch (std::out_of_range& e) { SWIG_exception(SWIG_IndexError,const_cast<char*>(e.what())); } } 9 Argument Handling
In Chapter 3, SWIG's treatment of basic datatypes and pointers was described. In particular, primitive types such as 9.1 The typemaps.i library
This section describes the 9.1.1 IntroductionSuppose you had a C function like this: void add(double a, double b, double *result) { *result = a + b; }
From reading the source code, it is clear that the function is storing a value in the
One way to deal with this is to use the // Simple example using typemaps %module example %include "typemaps.i" %apply double *OUTPUT { double *result }; %inlne %{ extern void add(double a, double b, double *result); %}
The When the resulting module is created, you can now use the function like this (shown for Python): >>> a = add(3,4) >>> print a 7 >>>
In this case, you can see how the output value normally returned in the third argument has magically been transformed into a function return value. Clearly this makes the function much easier to use since it is no longer necessary to manufacture a special Once a typemap has been applied to a type, it stays in effect for all future occurrences of the type and name. For example, you could write the following: %module example %include "typemaps.i" %apply double *OUTPUT { double *result }; %inline %{ extern void add(double a, double b, double *result); extern void sub(double a, double b, double *result); extern void mul(double a, double b, double *result); extern void div(double a, double b, double *result); %} ...
In this case, the Typemap transformations can even be extended to multiple return values. For example, consider this code: %include "typemaps.i" %apply int *OUTPUT { int *width, int *height }; // Returns a pair (width,height) void getwinsize(int winid, int *width, int *height); In this case, the function returns multiple values, allowing it to be used like this: >>> w,h = genwinsize(wid) >>> print w 400 >>> print h 300 >>>
It should also be noted that although the // Simple example using typemaps %module example %include "typemaps.i" %{ extern void add(double a, double b, double *OUTPUT); %} extern void add(double a, double b, double *OUTPUT);
Typemaps stay in effect until they are explicitly deleted or redefined to something else. To clear a typemap, the %clear double *result; // Remove all typemaps for double *result 9.1.2 Input parametersThe following typemaps instruct SWIG that a pointer really only holds a single input value: int *INPUT short *INPUT long *INPUT unsigned int *INPUT unsigned short *INPUT unsigned long *INPUT double *INPUT float *INPUT When used, it allows values to be passed instead of pointers. For example, consider this function: double add(double *a, double *b) { return *a+*b; } Now, consider this SWIG interface: %module example %include "typemaps.i" ... %{ extern double add(double *, double *); %} extern double add(double *INPUT, double *INPUT); When the function is used in the scripting language interpreter, it will work like this: result = add(3,4) 9.1.3 Output parametersThe following typemap rules tell SWIG that pointer is the output value of a function. When used, you do not need to supply the argument when calling the function. Instead, one or more output values are returned. int *OUTPUT short *OUTPUT long *OUTPUT unsigned int *OUTPUT unsigned short *OUTPUT unsigned long *OUTPUT double *OUTPUT float *OUTPUT These methods can be used as shown in an earlier example. For example, if you have this C function : void add(double a, double b, double *c) { *c = a+b; } A SWIG interface file might look like this : %module example %include "typemaps.i" ... %inline %{ extern void add(double a, double b, double *OUTPUT); %} In this case, only a single output value is returned, but this is not a restriction. An arbitrary number of output values can be returned by applying the output rules to more than one argument (as shown previously). If the function also returns a value, it is returned along with the argument. For example, if you had this: extern int foo(double a, double b, double *OUTPUT); The function will return two values like this: iresult, dresult = foo(3.5, 2) 9.1.4 Input/Output parametersWhen a pointer serves as both an input and output value you can use the following typemaps : int *INOUT short *INOUT long *INOUT unsigned int *INOUT unsigned short *INOUT unsigned long *INOUT double *INOUT float *INOUT A C function that uses this might be something like this: void negate(double *x) { *x = -(*x); } To make x function as both and input and output value, declare the function like this in an interface file : %module example %include "typemaps.i" ... %{ extern void negate(double *); %} extern void negate(double *INOUT); Now within a script, you can simply call the function normally : a = negate(3); # a = -3 after calling this
One subtle point of the
Compatibility note : The 9.1.5 Using different names
As previously shown, the // Make double *result an output value %apply double *OUTPUT { double *result }; // Make Int32 *in an input value %apply int *INPUT { Int32 *in }; // Make long *x inout %apply long *INOUT {long *x};
To clear a rule, the %clear double *result; %clear Int32 *in, long *x;
Typemap declarations are lexically scoped so a typemap takes effect from the point of definition to the end of the file or a matching 9.2 Applying constraints to input values
In addition to changing the handling of various input values, it is also possible to use typemaps to apply constraints. For example, maybe you want to insure that a value is positive, or that a pointer is non-NULL. This can be accomplished including the 9.2.1 Simple constraint exampleThe constraints library is best illustrated by the following interface file : // Interface file with constraints %module example %include "constraints.i" double exp(double x); double log(double POSITIVE); // Allow only positive values double sqrt(double NONNEGATIVE); // Non-negative values only double inv(double NONZERO); // Non-zero values void free(void *NONNULL); // Non-NULL pointers only The behavior of this file is exactly as you would expect. If any of the arguments violate the constraint condition, a scripting language exception will be raised. As a result, it is possible to catch bad values, prevent mysterious program crashes and so on. 9.2.2 Constraint methodsThe following constraints are currently available POSITIVE Any number > 0 (not zero) NEGATIVE Any number < 0 (not zero) NONNEGATIVE Any number >= 0 NONPOSITIVE Any number <= 0 NONZERO Nonzero number NONNULL Non-NULL pointer (pointers only). 9.2.3 Applying constraints to new datatypes
The constraints library only supports the primitive C datatypes, but it is easy to apply it to new datatypes using // Apply a constraint to a Real variable %apply Number POSITIVE { Real in }; // Apply a constraint to a pointer type %apply Pointer NONNULL { Vector * };
The special types of “Number” and “Pointer” can be applied to any numeric and pointer variable type respectively. To later remove a constraint, the %clear Real in; %clear Vector *; 10 Typemaps10.1 IntroductionChances are, you are reading this chapter for one of two reasons; you either want to customize SWIG's behavior or you overheard someone mumbling some incomprehensible drivel about “typemaps” and you asked yourself “typemaps, what are those?” That said, let's start with a short disclaimer that “typemaps” are an advanced customization feature that provide direct access to SWIG's low-level code generator. Not only that, they are an integral part of the SWIG C++ type system (a non-trivial topic of its own). Typemaps are generally not a required part of using SWIG. Therefore, you might want to re-read the earlier chapters if you have found your way to this chapter with only a vague idea of what SWIG already does by default. 10.1.1 Type conversionOne of the most important problems in wrapper code generation is the conversion of datatypes between programming languages. Specifically, for every C/C++ declaration, SWIG must somehow generate wrapper code that allows values to be passed back and forth between languages. Since every programming language represents data differently, this is not a simple of matter of simply linking code together with the C linker. Instead, SWIG has to know something about how data is represented in each language and how it can be manipulated. To illustrate, suppose you had a simple C function like this: int factorial(int n); To access this function from Python, a pair of Python API functions are used to convert integer values. For example: long PyInt_AsLong(PyObject *obj); /* Python --> C */ PyObject *PyInt_FromLong(long x); /* C --> Python */
The first function is used to convert the input argument from a Python integer object to C Inside the wrapper function, you might see these functions used like this: PyObject *wrap_factorial(PyObject *self, PyObject *args) { int arg1; int result; PyObject *obj1; PyObject *resultobj; if (!PyArg_ParseTuple("O:factorial", &obj1)) return NULL; arg1 = PyInt_AsLong(obj1); result = factorial(arg1); resultobj = PyInt_FromLong(result); return resultobj; } Every target language supported by SWIG has functions that work in a similar manner. For example, in Perl, the following functions are used: IV SvIV(SV *sv); /* Perl --> C */ void sv_setiv(SV *sv, IV val); /* C --> Perl */ In Tcl: int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *obj, long *value); Tcl_Obj *Tcl_NewIntObj(long value); The precise details are not so important. What is important is that all of the underlying type conversion is handled by collections of utility functions and short bits of C code like this—you simply have to read the extension documentation for your favorite language to know how it works (an exercise left to the reader). 10.1.2 Typemaps
Since type handling is so central to wrapper code generation, SWIG allows it to be completely defined (or redefined) by the user. To do this, a special /* Convert from Python --> C */ %typemap(in) int { $1 = PyInt_AsLong($input); } /* Convert from C --> Python */ %typemap(out) int { $result = PyInt_FromLong($1); }
At first glance, this code will look a little confusing. However, there is really not much to it. The first typemap (the “in” typemap) is used to convert a value from the target language to C. The second typemap (the “out” typemap) is used to convert in the other direction. The content of each typemap is a small fragment of code that is inserted directly into the SWIG generated wrapper functions. The code is usually C or C++ code which will be generated into the C/C++ wrapper functions. Note that this isn't always the case as some target language modules allow target language code within the typemaps which gets generated into target language specific files. Within this code, a number of special variables prefixed with a $ are expanded. These are really just placeholders for C/C++ variables that are generated in the course of creating the wrapper function. In this case, A short example might make this a little more clear. If you were wrapping a function like this: int gcd(int x, int y); A wrapper function would look approximately like this: PyObject *wrap_gcd(PyObject *self, PyObject *args) { int arg1; int arg2; int result; PyObject *obj1; PyObject *obj2; PyObject *resultobj; if (!PyArg_ParseTuple("OO:gcd", &obj1, &obj2)) return NULL; /* "in" typemap, argument 1 */ { arg1 = PyInt_AsLong(obj1); } /* "in" typemap, argument 2 */ { arg2 = PyInt_AsLong(obj2); } result = gcd(arg1,arg2); /* "out" typemap, return value */ { resultobj = PyInt_FromLong(result); } return resultobj; } In this code, you can see how the typemap code has been inserted into the function. You can also see how the special $ variables have been expanded to match certain variable names inside the wrapper function. This is really the whole idea behind typemaps–they simply let you insert arbitrary code into different parts of the generated wrapper functions. Because arbitrary code can be inserted, it possible to completely change the way in which values are converted. 10.1.3 Pattern matchingAs the name implies, the purpose of a typemap is to “map” C datatypes to types in the target language. Once a typemap is defined for a C datatype, it is applied to all future occurrences of that type in the input file. For example: /* Convert from Perl --> C */ %typemap(in) int { $1 = SvIV($input); } ... int factorial(int n); int gcd(int x, int y); int count(char *s, char *t, int max);
The matching of typemaps to C datatypes is more than a simple textual match. In fact, typemaps are fully built into the underlying type system. Therefore, typemaps are unaffected by /* Convert from Ruby--> C */ %typemap(in) int { $1 = NUM2INT($input); } ... typedef int Integer; namespace foo { typedef Integer Number; }; int foo(int x); int bar(Integer y); int spam(foo::Number a, foo::Number b);
In this case, the typemap is still applied to the proper arguments even though typenames don't always match the text “int”. This ability to track types is a critical part of SWIG–in fact, all of the target language modules work merely define a set of typemaps for the basic types. Yet, it is never necessary to write new typemaps for typenames introduced by In addition to tracking typenames, typemaps may also be specialized to match against a specific argument name. For example, you could write a typemap like this: %typemap(in) double nonnegative { $1 = PyFloat_AsDouble($input); if ($1 < 0) { PyErr_SetString(PyExc_ValueError,"argument must be nonnegative."); return NULL; } } ... double sin(double x); double cos(double x); double sqrt(double nonnegative); typedef double Real; double log(Real nonnegative); ... For certain tasks such as input argument conversion, typemaps can be defined for sequences of consecutive arguments. For example: %typemap(in) (char *str, int len) { $1 = PyString_AsString($input); /* char *str */ $2 = PyString_Size($input); /* int len */ } ... int count(char *str, int len, char c);
In this case, a single input object is expanded into a pair of C arguments. This example also provides a hint to the unusual variable naming scheme involving 10.1.4 Reusing typemapsTypemaps are normally defined for specific type and argument name patterns. However, typemaps can also be copied and reused. One way to do this is to use assignment like this: %typemap(in) Integer = int; %typemap(in) (char *buffer, int size) = (char *str, int len);
A more general form of copying is found in the %typemap(in) int { /* Convert an integer argument */ ... } %typemap(out) int { /* Return an integer value */ ... } /* Apply all of the integer typemaps to size_t */ %apply int { size_t };
It should be noted that it is not necessary to copy typemaps for types that are related by typedef int size_t;
then SWIG already knows that the 10.1.5 What can be done with typemaps?The primary use of typemaps is for defining wrapper generation behavior at the level of individual C/C++ datatypes. There are currently six general categories of problems that typemaps address: Argument handling int foo(int x, double y, char *s);
Return value handling int foo(int x, double y, char *s);
Exception handling int foo(int x, double y, char *s) throw(MemoryError, IndexError);
Global variables int foo;
Member variables struct Foo { int x[20]; };
Constant creation #define FOO 3 %constant int BAR = 42; enum { ALE, LAGER, STOUT };
Details of each of these typemaps will be covered shortly. Also, certain language modules may define additional typemaps that expand upon this list. For example, the Java module defines a variety of typemaps for controlling additional aspects of the Java bindings. Consult language specific documentation for further details. 10.1.6 What can't be done with typemaps?Typemaps can't be used to define properties that apply to C/C++ declarations as a whole. For example, suppose you had a declaration like this, Foo *make_Foo();
and you wanted to tell SWIG that Typemaps also can't be used to rearrange or transform the order of arguments. For example, if you had a function like this: void foo(int, char *); you can't use typemaps to interchange the arguments, allowing you to call the function like this: foo("hello",3) # Reversed arguments If you want to change the calling conventions of a function, write a helper function instead. For example: %rename(foo) wrap_foo; %inline %{ void wrap_foo(char *s, int x) { foo(x,s); } %} 10.1.7 The rest of this chapterThe rest of this chapter provides detailed information for people who want to write new typemaps. This information is of particular importance to anyone who intends to write a new SWIG target language module. Power users can also use this information to write application specific type conversion rules.
Since typemaps are strongly tied to the underlying C++ type system, subsequent sections assume that you are reasonably familiar with the basic details of values, pointers, references, arrays, type qualifiers (e.g., 10.2 Typemap specifications
This section describes the behavior of the 10.2.1 Defining a typemap
New typemaps are defined using the %typemap(method [, modifiers]) typelist code ;
method is a simply a name that specifies what kind of typemap is being defined. It is usually a name like
modifiers is an optional comma separated list of typelist is a list of the C++ type patterns that the typemap will match. The general form of this list is as follows: typelist : typepattern [, typepattern, typepattern, ... ] ; typepattern : type [ (parms) ] | type name [ (parms) ] | ( typelist ) [ (parms) ] Each type pattern is either a simple type, a simple type and argument name, or a list of types in the case of multi-argument typemaps. In addition, each type pattern can be parameterized with a list of temporary variables (parms). The purpose of these variables will be explained shortly. code specifies the code used in the typemap. Usually this is C/C++ code, but in the statically typed target languages, such as Java and C#, this can contain target language code for certain typemaps. It can take any one of the following forms: code : { ... } | " ... " | %{ ... %} Note that the preprocessor will expand code within the {} delimiters, but not in the last two styles of delimiters, see Preprocessor and Typemaps. Here are some examples of valid typemap specifications: /* Simple typemap declarations */ %typemap(in) int { $1 = PyInt_AsLong($input); } %typemap(in) int "$1 = PyInt_AsLong($input);"; %typemap(in) int %{ $1 = PyInt_AsLong($input); %} /* Typemap with extra argument name */ %typemap(in) int nonnegative { ... } /* Multiple types in one typemap */ %typemap(in) int, short, long { $1 = SvIV($input); } /* Typemap with modifiers */ %typemap(in,doc="integer") int "$1 = gh_scm2int($input);"; /* Typemap applied to patterns of multiple arguments */ %typemap(in) (char *str, int len), (char *buffer, int size) { $1 = PyString_AsString($input); $2 = PyString_Size($input); } /* Typemap with extra pattern parameters */ %typemap(in, numinputs=0) int *output (int temp), long *output (long temp) { $1 = &temp; } Admittedly, it's not the most readable syntax at first glance. However, the purpose of the individual pieces will become clear. 10.2.2 Typemap scopeOnce defined, a typemap remains in effect for all of the declarations that follow. A typemap may be redefined for different sections of an input file. For example: // typemap1 %typemap(in) int { ... } int fact(int); // typemap1 int gcd(int x, int y); // typemap1 // typemap2 %typemap(in) int { ... } int isprime(int); // typemap2
One exception to the typemap scoping rules pertains to the class Foo { ... }; %typemap(in) int { ... } %extend Foo { int blah(int x); // typemap has no effect. Declaration is attached to Foo which // appears before the %typemap declaration. }; 10.2.3 Copying a typemapA typemap is copied by using assignment. For example: %typemap(in) Integer = int; or this: %typemap(in) Integer, Number, int32_t = int; Types are often managed by a collection of different typemaps. For example: %typemap(in) int { ... } %typemap(out) int { ... } %typemap(varin) int { ... } %typemap(varout) int { ... }
To copy all of these typemaps to a new type, use %apply int { Integer }; // Copy all int typemaps to Integer %apply int { Integer, Number }; // Copy all int typemaps to both Integer and Number
The patterns for %apply int *output { Integer *output }; // Typemap with name %apply (char *buf, int len) { (char *buffer, int size) }; // Multiple arguments 10.2.4 Deleting a typemapA typemap can be deleted by simply defining no code. For example: %typemap(in) int; // Clears typemap for int %typemap(in) int, long, short; // Clears typemap for int, long, short %typemap(in) int *output;
The %clear int; // Removes all types for int %clear int *output, long *output;
Note: Since SWIG's default behavior is defined by typemaps, clearing a fundamental type like 10.2.5 Placement of typemapsTypemap declarations can be declared in the global scope, within a C++ namespace, and within a C++ class. For example: %typemap(in) int { ... } namespace std { class string; %typemap(in) string { ... } } class Bar { public: typedef const int & const_reference; %typemap(out) const_reference { ... } }; When a typemap appears inside a namespace or class, it stays in effect until the end of the SWIG input (just like before). However, the typemap takes the local scope into account. Therefore, this code namespace std { class string; %typemap(in) string { ... } }
is really defining a typemap for the type namespace std { class string; %typemap(in) string { /* std::string */ ... } } namespace Foo { class string; %typemap(in) string { /* Foo::string */ ... } }
In this case, there are two completely distinct typemaps that apply to two completely different types (
It should be noted that for scoping to work, SWIG has to know that 10.3 Pattern matching rulesThe section describes the pattern matching rules by which C datatypes are associated with typemaps. 10.3.1 Basic matching rules
Typemaps are matched using both a type and a name (typically the name of a argument). For a given
If
If
To illustrate, suppose that you had a function like this: int foo(const char *s);
To find a typemap for the argument const char *s Exact type and name match const char * Exact type match char *s Type and name match (stripped qualifiers) char * Type match (stripped qualifiers) When more than one typemap rule might be defined, only the first match found is actually used. Here is an example that shows how some of the basic rules are applied: %typemap(in) int *x { ... typemap 1 } %typemap(in) int * { ... typemap 2 } %typemap(in) const int *z { ... typemap 3 } %typemap(in) int [4] { ... typemap 4 } %typemap(in) int [ANY] { ... typemap 5 } void A(int *x); // int *x rule (typemap 1) void B(int *y); // int * rule (typemap 2) void C(const int *x); // int *x rule (typemap 1) void D(const int *z); // int * rule (typemap 3) void E(int x[4]); // int [4] rule (typemap 4) void F(int x[1000]); // int [ANY] rule (typemap 5) 10.3.2 Typedef reductionsIf no match is found using the rules in the previous section, SWIG applies a typedef reduction to the type and repeats the typemap search for the reduced type. To illustrate, suppose you had code like this: %typemap(in) int { ... typemap 1 } typedef int Integer; void blah(Integer x);
To find the typemap for Integer x Integer
Finding no match, it then applies a reduction int x int --> match: typemap 1 Even though two types might be the same via typedef, SWIG allows typemaps to be defined for each typename independently. This allows for interesting customization possibilities based solely on the typename itself. For example, you could write code like this: typedef double pdouble; // Positive double // typemap 1 %typemap(in) double { ... get a double ... } // typemap 2 %typemap(in) pdouble { ... get a positive double ... } double sin(double x); // typemap 1 pdouble sqrt(pdouble x); // typemap 2 When reducing the type, only one typedef reduction is applied at a time. The search process continues to apply reductions until a match is found or until no more reductions can be made. For complicated types, the reduction process can generate a long list of patterns. Consider the following: typedef int Integer; typedef Integer Row4[4]; void foo(Row4 rows[10]);
To find a match for the Row4 rows[10] Row4 [10] Row4 rows[ANY] Row4 [ANY] # Reduce Row4 --> Integer[4] Integer rows[10][4] Integer [10][4] Integer rows[ANY][ANY] Integer [ANY][ANY] # Reduce Integer --> int int rows[10][4] int [10][4] int rows[ANY][ANY] int [ANY][ANY] For parameterized types like templates, the situation is even more complicated. Suppose you had some declarations like this: typedef int Integer; typedef foo<Integer,Integer> fooii; void blah(fooii *x);
In this case, the following typemap patterns are searched for the argument fooii *x fooii * # Reduce fooii --> foo<Integer,Integer> foo<Integer,Integer> *x foo<Integer,Integer> * # Reduce Integer -> int foo<int, Integer> *x foo<int, Integer> * # Reduce Integer -> int foo<int, int> *x foo<int, int> *
Typemap reductions are always applied to the left-most type that appears. Only when no reductions can be made to the left-most type are reductions made to other parts of the type. This behavior means that you could define a typemap for 10.3.3 Default typemapsMost SWIG language modules use typemaps to define the default behavior of the C primitive types. This is entirely straightforward. For example, a set of typemaps are written like this: %typemap(in) int "convert an int"; %typemap(in) short "convert a short"; %typemap(in) float "convert a float"; ...
Since typemap matching follows all
The default behavior for pointers, arrays, references, and other kinds of types are handled by specifying rules for variations of the reserved %typemap(in) SWIGTYPE * { ... default pointer handling ... } %typemap(in) SWIGTYPE & { ... default reference handling ... } %typemap(in) SWIGTYPE [] { ... default array handling ... } %typemap(in) enum SWIGTYPE { ... default handling for enum values ... } %typemap(in) SWIGTYPE (CLASS::*) { ... default pointer member handling ... }
These rules match any kind of pointer, reference, or array–even when multiple levels of indirection or multiple array dimensions are used. Therefore, if you wanted to change SWIG's default handling for all types of pointers, you would simply redefine the rule for Finally, the following typemap rule is used to match against simple types that don't match any other rules: %typemap(in) SWIGTYPE { ... handle an unknown type ... } This typemap is important because it is the rule that gets triggered when call or return by value is used. For instance, if you have a declaration like this: double dot_product(Vector a, Vector b);
The
By redefining
The best way to explore the default typemaps is to look at the ones already defined for a particular language module. Typemaps definitions are usually found in the SWIG library in a file such as 10.3.4 Mixed default typemaps
The default typemaps described above can be mixed with %typemap(in) enum SWIGTYPE & { ... enum references ... } %typemap(in) const enum SWIGTYPE & { ... const enum references ... } %typemap(in) SWIGTYPE *& { ... pointers passed by reference ... } %typemap(in) SWIGTYPE * const & { ... constant pointers passed by reference ... } %typemap(in) SWIGTYPE[ANY][ANY] { ... 2D arrays ... } Note that the the typedef reduction described earlier is also used with these mixed default typemaps. For example, say the following typemaps are defined and SWIG is looking for the best match for the enum shown below: %typemap(in) const Hello & { ... } %typemap(in) const enum SWIGTYPE & { ... } %typemap(in) enum SWIGTYPE & { ... } %typemap(in) SWIGTYPE & { ... } %typemap(in) SWIGTYPE { ... } enum Hello {}; const Hello &hi; The typemap at the top of the list will be chosen, not because it is defined first, but because it is the closest match for the type being wrapped. If any of the typemaps in the above list were not defined, then the next one on the list would have precedence. In other words the typemap chosen is the closest explicit match. Compatibility note: The mixed default typemaps were introduced in SWIG-1.3.23, but were not used much in this version. Expect to see them being used more and more within the various libraries in later versions of SWIG. 10.3.5 Multi-arguments typemapsWhen multi-argument typemaps are specified, they take precedence over any typemaps specified for a single type. For example: %typemap(in) (char *buffer, int len) { // typemap 1 } %typemap(in) char *buffer { // typemap 2 } void foo(char *buffer, int len, int count); // (char *buffer, int len) void bar(char *buffer, int blah); // char *buffer Multi-argument typemaps are also more restrictive in the way that they are matched. Currently, the first argument follows the matching rules described in the previous section, but all subsequent arguments must match exactly. 10.4 Code generation rulesThis section describes rules by which typemap code is inserted into the generated wrapper code. 10.4.1 ScopeWhen a typemap is defined like this: %typemap(in) int { $1 = PyInt_AsLong($input); } the typemap code is inserted into the wrapper function using a new block scope. In other words, the wrapper code will look like this: wrap_whatever() { ... // Typemap code { arg1 = PyInt_AsLong(obj1); } ... } Because the typemap code is enclosed in its own block, it is legal to declare temporary variables for use during typemap execution. For example: %typemap(in) short { long temp; /* Temporary value */ if (Tcl_GetLongFromObj(interp, $input, &temp) != TCL_OK) { return TCL_ERROR; } $1 = (short) temp; } Of course, any variables that you declare inside a typemap are destroyed as soon as the typemap code has executed (they are not visible to other parts of the wrapper function or other typemaps that might use the same variable names). Occasionally, typemap code will be specified using a few alternative forms. For example: %typemap(in) int "$1 = PyInt_AsLong($input);"; %typemap(in) int %{ $1 = PyInt_AsLong($input); %} These two forms are mainly used for cosmetics–the specified code is not enclosed inside a block scope when it is emitted. This sometimes results in a less complicated looking wrapper function. 10.4.2 Declaring new local variablesSometimes it is useful to declare a new local variable that exists within the scope of the entire wrapper function. A good example of this might be an application in which you wanted to marshal strings. Suppose you had a C++ function like this int foo(std::string *s); and you wanted to pass a native string in the target language as an argument. For instance, in Perl, you wanted the function to work like this: $x = foo("Hello World");
To do this, you can't just pass a raw Perl string as the %typemap(in) std::string * (std::string temp) { unsigned int len; char *s; s = SvPV($input,len); /* Extract string data */ temp.assign(s,len); /* Assign to temp */ $1 = &temp; /* Set argument to point to temp */ }
In this case, wrap_foo() { std::string temp; <--- Declaration of temp goes here ... /* Typemap code */ { ... temp.assign(s,len); ... } ... }
When you set It is perfectly safe to use more than one typemap involving local variables in the same declaration. For example, you could declare a function as : void foo(std::string *x, std::string *y, std::string *z); This is safely handled because SWIG actually renames all local variable references by appending an argument number suffix. Therefore, the generated code would actually look like this: wrap_foo() { int *arg1; /* Actual arguments */ int *arg2; int *arg3; std::string temp1; /* Locals declared in the typemap */ std::string temp2; std::string temp3; ... { char *s; unsigned int len; ... temp1.assign(s,len); arg1 = *temp1; } { char *s; unsigned int len; ... temp2.assign(s,len); arg2 = &temp2; } { char *s; unsigned int len; ... temp3.assign(s,len); arg3 = &temp3; } ... } Some typemaps do not recognize local variables (or they may simply not apply). At this time, only typemaps that apply to argument conversion support this. Note: When declaring a typemap for multiple types, each type must have its own local variable declaration. %typemap(in) const std::string *, std::string * (std::string temp) // NO! // only std::string * has a local variable // const std::string * does not (oops) .... %typemap(in) const std::string * (std::string temp), std::string * (std::string temp) // Correct .... 10.4.3 Special variablesWithin all typemaps, the following special variables are expanded. This is by no means a complete list as some target languages have additional special variables which are documented in the language specific chapters.
Within the table, $n refers to a specific type within the typemap specification. For example, if you write this %typemap(in) int *INPUT { }
then $1 refers to %typemap(in) (int argc, char *argv[]) { ... }
then $1 refers to Substitutions related to types and names always fill in values from the actual code that was matched. This is useful when a typemap might match multiple C datatype. For example: %typemap(in) int, short, long { $1 = ($1_ltype) PyInt_AsLong($input); }
In this case,
When typemap code is emitted, the C/C++ datatype of the special variables type ltype ------ ---------------- int int const int int const int * int * int [4] int * int [4][5] int (*)[5] In most cases a ltype is simply the C datatype with qualifiers stripped off. In addition, arrays are converted into pointers.
Variables such as If necessary, type related substitutions can also be used when declaring locals. For example: %typemap(in) int * ($*1_type temp) { temp = PyInt_AsLong($input); $1 = &temp; }
There is one word of caution about declaring local variables in this manner. If you declare a local variable using a type substitution such as %typemap(in) int [10][20] { $1_ltype temp; }
then the declaration of int (*)[20] temp;
This is illegal C syntax and won't compile. There is currently no straightforward way to work around this problem in SWIG due to the way that typemap code is expanded and processed. However, one possible workaround is to simply pick an alternative type such as %typemap(in) int [10][20] { void *temp; ... (($1_ltype) temp)[i][j] = x; /* set a value */ ... }
Another approach, which only works for arrays is to use the %typemap(in) int [10][20] { $1_basetype temp[10][20]; ... temp[i][j] = x; /* set a value */ ... } 10.4.4 Special variable macros
Special variable macros are like macro functions in that they take one or more input arguments which are used for the macro expansion. They look like macro/function calls but use the special variable 10.4.4.1 $descriptor(type)
This macro expands into the type descriptor structure for any C/C++ type specified in 10.4.4.2 $typemap(method, typepattern)
This macro uses the pattern matching rules described earlier to lookup and then substitute the special variable macro with the code in the matched typemap. The typemap to search for is specified by the arguments, where The special variables within the matched typemap are expanded into those for the matched typemap type, not the typemap within which the macro is called. In practice, there is little use for this macro in the scripting target languages. It is mostly used in the target languages that are statically typed as a way to obtain the target language type given the C/C++ type and more commonly only when the C++ type is a template parameter. The example below is for C# only and uses some typemap method names documented in the C# chapter, but it shows some of the possible syntax variations. %typemap(cstype) unsigned long "uint" %typemap(cstype) unsigned long bb "bool" %typemap(cscode) BarClass %{ void foo($typemap(cstype, unsigned long aa) var1, $typemap(cstype, unsigned long bb) var2, $typemap(cstype, (unsigned long bb)) var3, $typemap(cstype, unsigned long) var4) { // do something } %} The result is the following expansion %typemap(cstype) unsigned long "uint" %typemap(cstype) unsigned long bb "bool" %typemap(cscode) BarClass %{ void foo(uint var1, bool var2, bool var3, uint var4) { // do something } %} 10.5 Common typemap methodsThe set of typemaps recognized by a language module may vary. However, the following typemap methods are nearly universal: 10.5.1 "in" typemapThe “in” typemap is used to convert function arguments from the target language to C. For example: %typemap(in) int { $1 = PyInt_AsLong($input); } The following special variables are available: $input - Input object holding value to be converted. $symname - Name of function/method being wrapped This is probably the most commonly redefined typemap because it can be used to implement customized conversions.
In addition, the “in” typemap allows the number of converted arguments to be specified. The // Ignored argument. %typemap(in, numinputs=0) int *out (int temp) { $1 = &temp; }
At this time, only zero or one arguments may be converted. When
Compatibility note: Specifying 10.5.2 "typecheck" typemapThe “typecheck” typemap is used to support overloaded functions and methods. It merely checks an argument to see whether or not it matches a specific type. For example: %typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) int { $1 = PyInt_Check($input) ? 1 : 0; } For typechecking, the $1 variable is always a simple integer that is set to 1 or 0 depending on whether or not the input argument is the correct type. If you define new “in” typemaps and your program uses overloaded methods, you should also define a collection of “typecheck” typemaps. More details about this follow in a later section on “Typemaps and Overloading.” 10.5.3 "out" typemapThe “out” typemap is used to convert function/method return values from C into the target language. For example: %typemap(out) int { $result = PyInt_FromLong($1); } The following special variables are available. $result - Result object returned to target language. $symname - Name of function/method being wrapped The “out” typemap supports an optional attribute flag called “optimal”. This is for code optimisation and is detailed in the Optimal code generation when returning by value section. 10.5.4 "arginit" typemapThe “arginit” typemap is used to set the initial value of a function argument–before any conversion has occurred. This is not normally necessary, but might be useful in highly specialized applications. For example: // Set argument to NULL before any conversion occurs %typemap(arginit) int *data { $1 = NULL; } 10.5.5 "default" typemapThe “default” typemap is used to turn an argument into a default argument. For example: %typemap(default) int flags { $1 = DEFAULT_FLAGS; } ... int foo(int x, int y, int flags); The primary use of this typemap is to either change the wrapping of default arguments or specify a default argument in a language where they aren't supported (like C). Target languages that do not support optional arguments, such as Java and C#, effectively ignore the value specified by this typemap as all arguments must be given. Once a default typemap has been applied to an argument, all arguments that follow must have default values. See the Default/optional arguments section for further information on default argument wrapping. 10.5.6 "check" typemapThe “check” typemap is used to supply value checking code during argument conversion. The typemap is applied after arguments have been converted. For example: %typemap(check) int positive { if ($1 <= 0) { SWIG_exception(SWIG_ValueError,"Expected positive value."); } } 10.5.7 "argout" typemapThe “argout” typemap is used to return values from arguments. This is most commonly used to write wrappers for C/C++ functions that need to return multiple values. The “argout” typemap is almost always combined with an “in” typemap—possibly to ignore the input value. For example: /* Set the input argument to point to a temporary variable */ %typemap(in, numinputs=0) int *out (int temp) { $1 = &temp; } %typemap(argout) int *out { // Append output value $1 to $result ... } The following special variables are available. $result - Result object returned to target language. $input - The original input object passed. $symname - Name of function/method being wrapped The code supplied to the “argout” typemap is always placed after the “out” typemap. If multiple return values are used, the extra return values are often appended to return value of the function.
See the 10.5.8 "freearg" typemapThe “freearg” typemap is used to cleanup argument data. It is only used when an argument might have allocated resources that need to be cleaned up when the wrapper function exits. The “freearg” typemap usually cleans up argument resources allocated by the “in” typemap. For example: // Get a list of integers %typemap(in) int *items { int nitems = Length($input); $1 = (int *) malloc(sizeof(int)*nitems); } // Free the list %typemap(freearg) int *items { free($1); }
The “freearg” typemap inserted at the end of the wrapper function, just before control is returned back to the target language. This code is also placed into a special variable 10.5.9 "newfree" typemap
The “newfree” typemap is used in conjunction with the %typemap(newfree) string * { delete $1; } %typemap(out) string * { $result = PyString_FromString($1->c_str()); } ... %newobject foo; ... string *foo(); See Object ownership and %newobject for further details. 10.5.10 "memberin" typemapThe “memberin” typemap is used to copy data from an already converted input value into a structure member. It is typically used to handle array members and other special cases. For example: %typemap(memberin) int [4] { memmove($1, $input, 4*sizeof(int)); } It is rarely necessary to write “memberin” typemaps—SWIG already provides a default implementation for arrays, strings, and other objects. 10.5.11 "varin" typemapThe “varin” typemap is used to convert objects in the target language to C for the purposes of assigning to a C/C++ global variable. This is implementation specific. 10.5.12 "varout" typemapThe “varout” typemap is used to convert a C/C++ object to an object in the target language when reading a C/C++ global variable. This is implementation specific. 10.5.13 "throws" typemap
The “throws” typemap is only used when SWIG parses a C++ method with an exception specification or has the %typemap(throws) const char * %{ PyErr_SetString(PyExc_RuntimeError, $1); SWIG_fail; %} void bar() throw (const char *); As can be seen from the generated code below, SWIG generates an exception handler with the catch block comprising the “throws” typemap content. ... try { bar(); } catch(char const *_e) { PyErr_SetString(PyExc_RuntimeError, _e); SWIG_fail; } ... Note that if your methods do not have an exception specification yet they do throw exceptions, SWIG cannot know how to deal with them. For a neat way to handle these, see the Exception handling with %exception section. 10.6 Some typemap examplesThis section contains a few examples. Consult language module documentation for more examples. 10.6.1 Typemaps for arraysA common use of typemaps is to provide support for C arrays appearing both as arguments to functions and as structure members. For example, suppose you had a function like this: void set_vector(int type, float value[4]);
If you wanted to handle %typemap(in) float value[4] (float temp[4]) { int i; if (!PySequence_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a sequence"); return NULL; } if (PySequence_Length($input) != 4) { PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 4 elements"); return NULL; } for (i = 0; i < 4; i++) { PyObject *o = PySequence_GetItem($input,i); if (PyNumber_Check(o)) { temp[i] = (float) PyFloat_AsDouble(o); } else { PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); return NULL; } } $1 = temp; }
In this example, the variable When used from Python, the typemap allows the following type of function call: >>> set_vector(type, [ 1, 2.5, 5, 20 ]) If you wanted to generalize the typemap to apply to arrays of all dimensions you might write this: %typemap(in) float value[ANY] (float temp[$1_dim0]) { int i; if (!PySequence_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a sequence"); return NULL; } if (PySequence_Length($input) != $1_dim0) { PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements"); return NULL; } for (i = 0; i < $1_dim0; i++) { PyObject *o = PySequence_GetItem($input,i); if (PyNumber_Check(o)) { temp[i] = (float) PyFloat_AsDouble(o); } else { PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); return NULL; } } $1 = temp; }
In this example, the special variable %typemap(in) float matrix[ANY][ANY] (float temp[$1_dim0][$1_dim1]) { ... convert a 2d array ... } For large arrays, it may be impractical to allocate storage on the stack using a temporary variable as shown. To work with heap allocated data, the following technique can be used. %typemap(in) float value[ANY] { int i; if (!PySequence_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a sequence"); return NULL; } if (PySequence_Length($input) != $1_dim0) { PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements"); return NULL; } $1 = (float *) malloc($1_dim0*sizeof(float)); for (i = 0; i < $1_dim0; i++) { PyObject *o = PySequence_GetItem($input,i); if (PyNumber_Check(o)) { $1[i] = (float) PyFloat_AsDouble(o); } else { PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); free($1); return NULL; } } } %typemap(freearg) float value[ANY] { if ($1) free($1); }
In this case, an array is allocated using Another common use of array typemaps is to provide support for array structure members. Due to subtle differences between pointers and arrays in C, you can't just “assign” to a array structure member. Instead, you have to explicitly copy elements into the array. For example, suppose you had a structure like this: struct SomeObject { float value[4]; ... };
When SWIG runs, it won't produce any code to set the swig -python example.i Generating wrappers for Python example.i:10. Warning. Array member value will be read-only.
These warning messages indicate that SWIG does not know how you want to set the To fix this, you can supply a special “memberin” typemap like this: %typemap(memberin) float [ANY] { int i; for (i = 0; i < $1_dim0; i++) { $1[i] = $input[i]; } }
The memberin typemap is used to set a structure member from data that has already been converted from the target language to C. In this case, When combined with the earlier typemaps for arrays, the combination of the “in” and “memberin” typemap allows the following usage: >>> s = SomeObject() >>> s.x = [1, 2.5, 5, 10] Related to structure member input, it may be desirable to return structure members as a new kind of object. For example, in this example, you will get very odd program behavior where the structure member can be set nicely, but reading the member simply returns a pointer: >>> s = SomeObject() >>> s.x = [1, 2.5, 5, 10] >>> print s.x _1008fea8_p_float >>> To fix this, you can write an “out” typemap. For example: %typemap(out) float [ANY] { int i; $result = PyList_New($1_dim0); for (i = 0; i < $1_dim0; i++) { PyObject *o = PyFloat_FromDouble((double) $1[i]); PyList_SetItem($result,i,o); } } Now, you will find that member access is quite nice: >>> s = SomeObject() >>> s.x = [1, 2.5, 5, 10] >>> print s.x [ 1, 2.5, 5, 10] Compatibility Note: SWIG1.1 used to provide a special “memberout” typemap. However, it was mostly useless and has since been eliminated. To return structure members, simply use the “out” typemap. 10.6.2 Implementing constraints with typemapsOne particularly interesting application of typemaps is the implementation of argument constraints. This can be done with the “check” typemap. When used, this allows you to provide code for checking the values of function arguments. For example : %module math %typemap(check) double posdouble { if ($1 < 0) { croak("Expecting a positive number"); } } ... double sqrt(double posdouble); This provides a sanity check to your wrapper function. If a negative number is passed to this function, a Perl exception will be raised and your program terminated with an error message. This kind of checking can be particularly useful when working with pointers. For example : %typemap(check) Vector * { if ($1 == 0) { PyErr_SetString(PyExc_TypeError,"NULL Pointer not allowed"); return NULL; } }
will prevent any function involving a Note: A more advanced constraint checking system is in development. Stay tuned. 10.7 Typemaps for multiple languagesThe code within typemaps is usually language dependent, however, many languages support the same typemaps. In order to distinguish typemaps across different languages, the preprocessor should be used. For example, the “in” typemap for Perl and Ruby could be written as: #if defined(SWIGPERL) %typemap(in) int "$1 = ($1_ltype) SvIV($input);" #elif defined(SWIGRUBY) %typemap(in) int "$1 = NUM2INT($input);" #else #warning no "in" typemap defined #endif The full set of language specific macros is defined in the Conditional Compilation section. The example above also shows a common approach of issuing a warning for an as yet unsupported language.
Compatibility note: In SWIG-1.1 different languages could be distinguished with the language name being put within the 10.8 Optimal code generation when returning by valueThe “out” typemap is the main typemap for return types. This typemap supports an optional attribute flag called “optimal”, which is for reducing temporary variables and the amount of generated code, thereby giving the compiler the opportunity to use return value optimization for generating faster executing code. It only really makes a difference when returning objects by value and has some limitations on usage, as explained later on. When a function returns an object by value, SWIG generates code that instantiates the default type on the stack then assigns the value returned by the function call to it. A copy of this object is then made on the heap and this is what is ultimately stored and used from the target language. This will be clearer considering an example. Consider running the following code through SWIG: %typemap(out) SWIGTYPE %{ $result = new $1_ltype((const $1_ltype &)$1); %} %inline %{ #include <iostream> using namespace std; struct XX { XX() { cout << "XX()" << endl; } XX(int i) { cout << "XX(" << i << ")" << endl; } XX(const XX &other) { cout << "XX(const XX &)" << endl; } XX & operator =(const XX &other) { cout << "operator=(const XX &)" << endl; return *this; } ~XX() { cout << "~XX()" << endl; } static XX create() { return XX(0); } }; %}
The “out” typemap shown is the default typemap for C# when returning by objects by value. When making a call to XX() XX(0) operator=(const XX &) ~XX() XX(const XX &) ~XX() ~XX()
Note that three objects are being created as well as an assignment. Wouldn't it be great if the %typemap(out, optimal="1") SWIGTYPE %{ $result = new $1_ltype((const $1_ltype &)$1); %} then when the code is run again, the output is simply: XX(0) ~XX() How the “optimal” attribute works is best explained using the generated code. Without “optimal”, the generated code is: SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() { void * jresult ; XX result; result = XX::create(); jresult = new XX((const XX &)result); return jresult; } With the “optimal” attribute, the code is: SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() { void * jresult ; jresult = new XX((const XX &)XX::create()); return jresult; }
The major difference is the
The “optimal” attribute optimisation is not turned on by default as it has a number of restrictions. Firstly, some code cannot be condensed into a simple call for passing into the copy constructor. One common occurrence is when %exception is used. Consider adding the following %exception XX::create() %{ try { $action } catch(const std::exception &e) { cout << e.what() << endl; } %} SWIG can detect when the “optimal” attribute cannot be used and will ignore it and in this case will issue the following warning: example.i:28: Warning(474): Method XX::create() usage of the optimal attribute in the out typemap at example.i:14 ignored as the following cannot be used to generate optimal code: try { result = XX::create(); } catch(const std::exception &e) { cout << e.what() << endl; }
It should be clear that the above code cannot be used as the argument to the copy constructor call, ie for the
Secondly, if the typemaps uses example.i:21: Warning(475): Multiple calls to XX::create() might be generated due to optimal attribute usage in the out typemap at example.i:7.
However, it doesn't always get it right, for example when 10.9 Multi-argument typemapsSo far, the typemaps presented have focused on the problem of dealing with single values. For example, converting a single input object to a single argument in a function call. However, certain conversion problems are difficult to handle in this manner. As an example, consider the example at the very beginning of this chapter: int foo(int argc, char *argv[]); Suppose that you wanted to wrap this function so that it accepted a single list of strings like this: >>> foo(["ale","lager","stout"])
To do this, you not only need to map a list of strings to A multi-argument typemap is a conversion rule that specifies how to convert a single object in the target language to set of consecutive function arguments in C/C++. For example, the following multi-argument maps perform the conversion described for the above example: %typemap(in) (int argc, char *argv[]) { int i; if (!PyList_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a list"); return NULL; } $1 = PyList_Size($input); $2 = (char **) malloc(($1+1)*sizeof(char *)); for (i = 0; i < $1; i++) { PyObject *s = PyList_GetItem($input,i); if (!PyString_Check(s)) { free($2); PyErr_SetString(PyExc_ValueError, "List items must be strings"); return NULL; } $2[i] = PyString_AsString(s); } $2[i] = 0; } %typemap(freearg) (int argc, char *argv[]) { if ($2) free($2); } A multi-argument map is always specified by surrounding the arguments with parentheses as shown. For example: %typemap(in) (int argc, char *argv[]) { ... }
Within the typemap code, the variables Multi-argument typemaps always have precedence over simple typemaps and SWIG always performs longest-match searching. Therefore, you will get the following behavior: %typemap(in) int argc { ... typemap 1 ... } %typemap(in) (int argc, char *argv[]) { ... typemap 2 ... } %typemap(in) (int argc, char *argv[], char *env[]) { ... typemap 3 ... } int foo(int argc, char *argv[]); // Uses typemap 2 int bar(int argc, int x); // Uses typemap 1 int spam(int argc, char *argv[], char *env[]); // Uses typemap 3 It should be stressed that multi-argument typemaps can appear anywhere in a function declaration and can appear more than once. For example, you could write this: %typemap(in) (int scount, char *swords[]) { ... } %typemap(in) (int wcount, char *words[]) { ... } void search_words(int scount, char *swords[], int wcount, char *words[], int maxcount);
Other directives such as %apply (int argc, char *argv[]) { (int scount, char *swords[]), (int wcount, char *words[]) }; ... %clear (int scount, char *swords[]), (int wcount, char *words[]); ...
Although multi-argument typemaps may seem like an exotic, little used feature, there are several situations where they make sense. First, suppose you wanted to wrap functions similar to the low-level typedef unsigned int size_t; int read(int fd, void *rbuffer, size_t len); int write(int fd, void *wbuffer, size_t len); As is, the only way to use the functions would be to allocate memory and pass some kind of pointer as the second argument—a process that might require the use of a helper function. However, using multi-argument maps, the functions can be transformed into something more natural. For example, you might write typemaps like this: // typemap for an outgoing buffer %typemap(in) (void *wbuffer, size_t len) { if (!PyString_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a string"); return NULL; } $1 = (void *) PyString_AsString($input); $2 = PyString_Size($input); } // typemap for an incoming buffer %typemap(in) (void *rbuffer, size_t len) { if (!PyInt_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting an integer"); return NULL; } $2 = PyInt_AsLong($input); if ($2 < 0) { PyErr_SetString(PyExc_ValueError, "Positive integer expected"); return NULL; } $1 = (void *) malloc($2); } // Return the buffer. Discarding any previous return result %typemap(argout) (void *rbuffer, size_t len) { Py_XDECREF($result); /* Blow away any previous result */ if (result < 0) { /* Check for I/O error */ free($1); PyErr_SetFromErrno(PyExc_IOError); return NULL; } $result = PyString_FromStringAndSize($1,result); free($1); }
(note: In the above example, Now, in a script, you can write code that simply passes buffers as strings like this: >>> f = example.open("Makefile") >>> example.read(f,40) 'TOP = ../..\nSWIG = $(TOP)/.' >>> example.read(f,40) './swig\nSRCS = example.c\nTARGET ' >>> example.close(f) 0 >>> g = example.open("foo", example.O_WRONLY | example.O_CREAT, 0644) >>> example.write(g,"Hello world\n") 12 >>> example.write(g,"This is a test\n") 15 >>> example.close(g) 0 >>> A number of multi-argument typemap problems also arise in libraries that perform matrix-calculations–especially if they are mapped onto low-level Fortran or C code. For example, you might have a function like this: int is_symmetric(double *mat, int rows, int columns); In this case, you might want to pass some kind of higher-level object as an matrix. To do this, you could write a multi-argument typemap like this: %typemap(in) (double *mat, int rows, int columns) { MatrixObject *a; a = GetMatrixFromObject($input); /* Get matrix somehow */ /* Get matrix properties */ $1 = GetPointer(a); $2 = GetRows(a); $3 = GetColumns(a); } This kind of technique can be used to hook into scripting-language matrix packages such as Numeric Python. However, it should also be stressed that some care is in order. For example, when crossing languages you may need to worry about issues such as row-major vs. column-major ordering (and perform conversions if needed). 10.10 The run-time type checkerMost scripting languages need type information at run-time. This type information can include how to construct types, how to garbage collect types, and the inheritance relationships between types. If the language interface does not provide its own type information storage, the generated SWIG code needs to provide it. Requirements for the type system:
10.10.1 ImplementationThe run-time type checker is used by many, but not all, of SWIG's supported target languages. The run-time type checker features are not required and are thus not used for strongly typed languages such as Java and C#. The scripting and scheme based languages rely on it and it forms a critical part of SWIG's operation for these languages.
When pointers, arrays, and objects are wrapped by SWIG, they are normally converted into typed pointer objects. For example, an instance of _108e688_p_Foo At a basic level, the type checker simply restores some type-safety to extension modules. However, the type checker is also responsible for making sure that wrapped C++ classes are handled correctly—especially when inheritance is used. This is especially important when an extension module makes use of multiple inheritance. For example: class Foo { int x; }; class Bar { int y; }; class FooBar : public Foo, public Bar { int z; };
When the class FooBar --> | -----------| <-- Foo | int x | |------------| <-- Bar | int y | |------------| | int z | |------------|
Because of the way that base class data is stacked together, the casting of a In the wrapper code generated for each language, pointers are handled through the use of special type descriptors and conversion functions. For example, if you look at the wrapper code for Python, you will see code like this: if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Foo,1)) == -1) return NULL;
In this code, The actual type code is in swigrun.swg, and gets inserted near the top of the generated swig wrapper file. The phrase “a type X that can cast into a type Y” means that given a type X, it can be converted into a type Y. In other words, X is a derived class of Y or X is a typedef of Y. The structure to store type information looks like this: /* Structure to store information on one type */ typedef struct swig_type_info { const char *name; /* mangled name of this type */ const char *str; /* human readable name for this type */ swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ struct swig_cast_info *cast; /* Linked list of types that can cast into this type */ void *clientdata; /* Language specific type data */ } swig_type_info; /* Structure to store a type and conversion function used for casting */ typedef struct swig_cast_info { swig_type_info *type; /* pointer to type that is equivalent to this type */ swig_converter_func converter; /* function to cast the void pointers */ struct swig_cast_info *next; /* pointer to next cast in linked list */ struct swig_cast_info *prev; /* pointer to the previous cast */ } swig_cast_info;
Each
The basic problem we need to solve is verifying and building arguments passed to functions. So going back to the
Another issue needing to be addressed is sharing type information between multiple modules. More explicitly, we need to have ONE Each module has one swig_module_info structure which looks like this: /* Structure used to store module information * Each module generates one structure like this, and the runtime collects * all of these structures and stores them in a circularly linked list.*/ typedef struct swig_module_info { swig_type_info **types; /* Array of pointers to swig_type_info structs in this module */ int size; /* Number of types in this module */ struct swig_module_info *next; /* Pointer to next element in circularly linked list */ swig_type_info **type_initial; /* Array of initially generated type structures */ swig_cast_info **cast_initial; /* Array of initially generated casting structures */ void *clientdata; /* Language specific module data */ } swig_module_info;
Each module stores an array of pointers to 10.10.2 UsageThis section covers how to use these functions from typemaps. To learn how to call these functions from external files (not the generated _wrap.c file), see the External access to the run-time system section. When pointers are converted in a typemap, the typemap code often looks similar to this: %typemap(in) Foo * { if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) return NULL; }
The most critical part is the typemap is the use of the
There is another reason why you should always use the
Occasionally, you might need to write a typemap that needs to convert pointers of other types. To handle this, the special variable macro %typemap(in) Foo * { if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) { Bar *temp; if ((SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *)) == -1) { return NULL; } $1 = (Foo *) temp; } }
The primary use of
In certain cases, SWIG may not generate type-descriptors like you expect. For example, if you are converting pointers in some non-standard way or working with an unusual combination of interface files and modules, you may find that SWIG omits information for a specific type descriptor. To fix this, you may need to use the %types(int *, short *, long *, float *, double *);
When
Further details about the run-time type checking can be found in the documentation for individual language modules. Reading the source code may also help. The file 10.11 Typemaps and overloadingIn many target languages, SWIG fully supports C++ overloaded methods and functions. For example, if you have a collection of functions like this: int foo(int x); int foo(double x); int foo(char *s, int y); You can access the functions in a normal way from the scripting interpreter: # Python foo(3) # foo(int) foo(3.5) # foo(double) foo("hello",5) # foo(char *, int) # Tcl foo 3 # foo(int) foo 3.5 # foo(double) foo hello 5 # foo(char *, int) To implement overloading, SWIG generates a separate wrapper function for each overloaded method. For example, the above functions would produce something roughly like this: // wrapper pseudocode _wrap_foo_0(argc, args[]) { // foo(int) int arg1; int result; ... arg1 = FromInteger(args[0]); result = foo(arg1); return ToInteger(result); } _wrap_foo_1(argc, args[]) { // foo(double) double arg1; int result; ... arg1 = FromDouble(args[0]); result = foo(arg1); return ToInteger(result); } _wrap_foo_2(argc, args[]) { // foo(char *, int) char *arg1; int arg2; int result; ... arg1 = FromString(args[0]); arg2 = FromInteger(args[1]); result = foo(arg1,arg2); return ToInteger(result); } Next, a dynamic dispatch function is generated: _wrap_foo(argc, args[]) { if (argc == 1) { if (IsInteger(args[0])) { return _wrap_foo_0(argc,args); } if (IsDouble(args[0])) { return _wrap_foo_1(argc,args); } } if (argc == 2) { if (IsString(args[0]) && IsInteger(args[1])) { return _wrap_foo_2(argc,args); } } error("No matching function!\n"); } The purpose of the dynamic dispatch function is to select the appropriate C++ function based on argument types—a task that must be performed at runtime in most of SWIG's target languages. The generation of the dynamic dispatch function is a relatively tricky affair. Not only must input typemaps be taken into account (these typemaps can radically change the types of arguments accepted), but overloaded methods must also be sorted and checked in a very specific order to resolve potential ambiguity. A high-level overview of this ranking process is found in the “SWIG and C++ ” chapter. What isn't mentioned in that chapter is the mechanism by which it is implemented—as a collection of typemaps. To support dynamic dispatch, SWIG first defines a general purpose type hierarchy as follows: Symbolic Name Precedence Value ------------------------------ ------------------ SWIG_TYPECHECK_POINTER 0 SWIG_TYPECHECK_VOIDPTR 10 SWIG_TYPECHECK_BOOL 15 SWIG_TYPECHECK_UINT8 20 SWIG_TYPECHECK_INT8 25 SWIG_TYPECHECK_UINT16 30 SWIG_TYPECHECK_INT16 35 SWIG_TYPECHECK_UINT32 40 SWIG_TYPECHECK_INT32 45 SWIG_TYPECHECK_UINT64 50 SWIG_TYPECHECK_INT64 55 SWIG_TYPECHECK_UINT128 60 SWIG_TYPECHECK_INT128 65 SWIG_TYPECHECK_INTEGER 70 SWIG_TYPECHECK_FLOAT 80 SWIG_TYPECHECK_DOUBLE 90 SWIG_TYPECHECK_COMPLEX 100 SWIG_TYPECHECK_UNICHAR 110 SWIG_TYPECHECK_UNISTRING 120 SWIG_TYPECHECK_CHAR 130 SWIG_TYPECHECK_STRING 140 SWIG_TYPECHECK_BOOL_ARRAY 1015 SWIG_TYPECHECK_INT8_ARRAY 1025 SWIG_TYPECHECK_INT16_ARRAY 1035 SWIG_TYPECHECK_INT32_ARRAY 1045 SWIG_TYPECHECK_INT64_ARRAY 1055 SWIG_TYPECHECK_INT128_ARRAY 1065 SWIG_TYPECHECK_FLOAT_ARRAY 1080 SWIG_TYPECHECK_DOUBLE_ARRAY 1090 SWIG_TYPECHECK_CHAR_ARRAY 1130 SWIG_TYPECHECK_STRING_ARRAY 1140
(These precedence levels are defined in In this table, the precedence-level determines the order in which types are going to be checked. Low values are always checked before higher values. For example, integers are checked before floats, single values are checked before arrays, and so forth. Using the above table as a guide, each target language defines a collection of “typecheck” typemaps. The follow excerpt from the Python module illustrates this: /* Python type checking rules */ /* Note: %typecheck(X) is a macro for %typemap(typecheck,precedence=X) */ %typecheck(SWIG_TYPECHECK_INTEGER) int, short, long, unsigned int, unsigned short, unsigned long, signed char, unsigned char, long long, unsigned long long, const int &, const short &, const long &, const unsigned int &, const unsigned short &, const unsigned long &, const long long &, const unsigned long long &, enum SWIGTYPE, bool, const bool & { $1 = (PyInt_Check($input) || PyLong_Check($input)) ? 1 : 0; } %typecheck(SWIG_TYPECHECK_DOUBLE) float, double, const float &, const double & { $1 = (PyFloat_Check($input) || PyInt_Check($input) || PyLong_Check($input)) ? 1 : 0; } %typecheck(SWIG_TYPECHECK_CHAR) char { $1 = (PyString_Check($input) && (PyString_Size($input) == 1)) ? 1 : 0; } %typecheck(SWIG_TYPECHECK_STRING) char * { $1 = PyString_Check($input) ? 1 : 0; } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] { void *ptr; if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0) == -1) { $1 = 0; PyErr_Clear(); } else { $1 = 1; } } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *ptr; if (SWIG_ConvertPtr($input, (void **) &ptr, $&1_descriptor, 0) == -1) { $1 = 0; PyErr_Clear(); } else { $1 = 1; } } %typecheck(SWIG_TYPECHECK_VOIDPTR) void * { void *ptr; if (SWIG_ConvertPtr($input, (void **) &ptr, 0, 0) == -1) { $1 = 0; PyErr_Clear(); } else { $1 = 1; } } %typecheck(SWIG_TYPECHECK_POINTER) PyObject * { $1 = ($input != 0); } It might take a bit of contemplation, but this code has merely organized all of the basic C++ types, provided some simple type-checking code, and assigned each type a precedence value. Finally, to generate the dynamic dispatch function, SWIG uses the following algorithm:
If you haven't written any typemaps of your own, it is unnecessary to worry about the typechecking rules. However, if you have written new input typemaps, you might have to supply a typechecking rule as well. An easy way to do this is to simply copy one of the existing typechecking rules. Here is an example, // Typemap for a C++ string %typemap(in) std::string { if (PyString_Check($input)) { $1 = std::string(PyString_AsString($input)); } else { SWIG_exception(SWIG_TypeError, "string expected"); } } // Copy the typecheck code for "char *". %typemap(typecheck) std::string = char *; The bottom line: If you are writing new typemaps and you are using overloaded methods, you will probably have to write typecheck code or copy existing code. Since this is a relatively new SWIG feature, there are few examples to work with. However, you might look at some of the existing library files likes 'typemaps.i' for a guide. Notes:
10.12 More about %apply and %clearIn order to implement certain kinds of program behavior, it is sometimes necessary to write sets of typemaps. For example, to support output arguments, one often writes a set of typemaps like this: %typemap(in,numinputs=0) int *OUTPUT (int temp) { $1 = &temp; } %typemap(argout) int *OUTPUT { // return value somehow }
To make it easier to apply the typemap to different argument types and names, the %apply int *OUTPUT { int *retvalue, int32 *output };
then all of the
However, there is a subtle aspect of
For example: %typemap(in) int *INPUT (int temp) { temp = ... get value from $input ...; $1 = &temp; } %typemap(check) int *POSITIVE { if (*$1 <= 0) { SWIG_exception(SWIG_ValueError,"Expected a positive number!\n"); return NULL; } } ... %apply int *INPUT { int *invalue }; %apply int *POSITIVE { int *invalue };
Since %clear int *invalue; 10.13 Reducing wrapper code sizeSince the code supplied to a typemap is inlined directly into wrapper functions, typemaps can result in a tremendous amount of code bloat. For example, consider this typemap for an array: %typemap(in) float [ANY] { int i; if (!PySequence_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a sequence"); return NULL; } if (PySequence_Length($input) != $1_dim0) { PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements"); return NULL; } $1 = (float) malloc($1_dim0*sizeof(float)); for (i = 0; i < $1_dim0; i++) { PyObject *o = PySequence_GetItem($input,i); if (PyNumber_Check(o)) { $1[i] = (float) PyFloat_AsDouble(o); } else { PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); free(result); return NULL; } } } If you had a large interface with hundreds of functions all accepting array parameters, this typemap would be replicated repeatedly–generating a huge amount of code. A better approach might be to consolidate some of the typemap into a function. For example: %{ /* Define a helper function */ static float * convert_float_array(PyObject *input, int size) { int i; float *result; if (!PySequence_Check(input)) { PyErr_SetString(PyExc_ValueError,"Expected a sequence"); return NULL; } if (PySequence_Length(input) != size) { PyErr_SetString(PyExc_ValueError,"Size mismatch. "); return NULL; } result = (float) malloc(size*sizeof(float)); for (i = 0; i < size; i++) { PyObject *o = PySequence_GetItem(input,i); if (PyNumber_Check(o)) { result[i] = (float) PyFloat_AsDouble(o); } else { PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); free(result); return NULL; } } return result; } %} %typemap(in) float [ANY] { $1 = convert_float_array($input, $1_dim0); if (!$1) return NULL; } %} 10.14 Passing data between typemapsIt is also important to note that the primary use of local variables is to create stack-allocated objects for temporary use inside a wrapper function (this is faster and less-prone to error than allocating data on the heap). In general, the variables are not intended to pass information between different types of typemaps. However, this can be done if you realize that local names have the argument number appended to them. For example, you could do this: %typemap(in) int *(int temp) { temp = (int) PyInt_AsLong($input); $1 = &temp; } %typemap(argout) int * { PyObject *o = PyInt_FromLong(temp$argnum); ... }
In this case, the 10.15 C++ "this" pointer
All the rules discussed for Typemaps apply to C++ as well as C. However in addition C++ passes an extra parameter into every non-static class method – the
In order to customise the For example, if wrapping for Java generation: %typemap(check) SWIGTYPE *self %{ if (!$1) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "swigCPtr null"); return $null; } %}
In the above case, the if (!arg1) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "invalid native object; delete() likely already called"); return ; } (arg1)->wrappedFunction(...);
Note that if you have a parameter named 10.16 Where to go for more information?
The best place to find out more information about writing typemaps is to look in the SWIG library. Most language modules define all of their default behavior using typemaps. These are found in files such as 11 Customization FeaturesIn many cases, it is desirable to change the default wrapping of particular declarations in an interface. For example, you might want to provide hooks for catching C++ exceptions, add assertions, or provide hints to the underlying code generator. This chapter describes some of these customization techniques. First, a discussion of exception handling is presented. Then, a more general-purpose customization mechanism known as “features” is described. 11.1 Exception handling with %exception
The %exception { try { $action } catch (RangeError) { PyErr_SetString(PyExc_IndexError,"index out-of-bounds"); return NULL; } }
When defined, the code enclosed in braces is inserted directly into the low-level wrapper functions. The special variable %exception; // Deletes any previously defined handler
Compatibility note: Previous versions of SWIG used a special directive 11.1.1 Handling exceptions in C codeC has no formal exception handling mechanism so there are several approaches that might be used. A somewhat common technique is to simply set a special error code. For example: /* File : except.c */ static char error_message[256]; static int error_status = 0; void throw_exception(char *msg) { strncpy(error_message,msg,256); error_status = 1; } void clear_exception() { error_status = 0; } char *check_exception() { if (error_status) return error_message; else return NULL; }
To use these functions, functions simply call double inv(double x) { if (x != 0) return 1.0/x; else { throw_exception("Division by zero"); return 0; } } To catch the exception, you can write a simple exception handler such as the following (shown for Perl5) : %exception { char *err; clear_exception(); $action if ((err = check_exception())) { croak(err); } }
In this case, when an error occurs, it is translated into a Perl error. Each target language has its own approach to creating a runtime error/exception in and for Perl it is the 11.1.2 Exception handling with longjmp()
Exception handling can also be added to C code using the /* File : except.c Just the declaration of a few global variables we're going to use */ #include <setjmp.h> jmp_buf exception_buffer; int exception_status; /* File : except.h */ #include <setjmp.h> extern jmp_buf exception_buffer; extern int exception_status; #define try if ((exception_status = setjmp(exception_buffer)) == 0) #define catch(val) else if (exception_status == val) #define throw(val) longjmp(exception_buffer,val) #define finally else /* Exception codes */ #define RangeError 1 #define DivisionByZero 2 #define OutOfMemory 3 Now, within a C program, you can do the following : double inv(double x) { if (x) return 1.0/x; else throw(DivisionByZero); } Finally, to create a SWIG exception handler, write the following : %{ #include "except.h" %} %exception { try { $action } catch(RangeError) { croak("Range Error"); } catch(DivisionByZero) { croak("Division by zero"); } catch(OutOfMemory) { croak("Out of memory"); } finally { croak("Unknown exception"); } }
Note: This implementation is only intended to illustrate the general idea. To make it work better, you'll need to modify it to handle nested 11.1.3 Handling C++ exceptionsHandling C++ exceptions is also straightforward. For example: %exception { try { $action } catch(RangeError) { croak("Range Error"); } catch(DivisionByZero) { croak("Division by zero"); } catch(OutOfMemory) { croak("Out of memory"); } catch(...) { croak("Unknown exception"); } } The exception types need to be declared as classes elsewhere, possibly in a header file : class RangeError {}; class DivisionByZero {}; class OutOfMemory {}; 11.1.4 Exception handlers for variables
By default all variables will ignore %allowexception; // turn on globally %allowexception Klass::MyVar; // turn on for a specific variable %noallowexception Klass::MyVar; // turn off for a specific variable %noallowexception; // turn off globally 11.1.5 Defining different exception handlers
By default, the
To fix this, you can be more selective about how you use the %exception { ... your exception handler ... } /* Define critical operations that can throw exceptions here */ %exception; /* Define non-critical operations that don't throw exceptions */ More precise control over exception handling can be obtained by attaching an exception handler to specific declaration name. For example: %exception allocate { try { $action } catch (MemoryError) { croak("Out of memory"); } }
In this case, the exception handler is only attached to declarations named “allocate”. This would include both global and member functions. The names supplied to %exception Object::allocate { try { $action } catch (MemoryError) { croak("Out of memory"); } } When a class prefix is supplied, the exception handler is applied to the corresponding declaration in the specified class as well as for identically named functions appearing in derived classes.
%exception Object::allocate(int) { try { $action } catch (MemoryError) { croak("Out of memory"); } } Attaching exceptions to specific declarations is a good way to reduce code bloat. It can also be a useful way to attach exceptions to specific parts of a header file. For example: %module example %{ #include "someheader.h" %} // Define a few exception handlers for specific declarations %exception Object::allocate(int) { try { $action } catch (MemoryError) { croak("Out of memory"); } } %exception Object::getitem { try { $action } catch (RangeError) { croak("Index out of range"); } } ... // Read a raw header file %include "someheader.h"
Compatibility note: The 11.1.6 Special variables for %exceptionThe %exception directive supports a few special variables which are placeholders for code substitution. The following table shows the available special variables and details what the special variables are replaced with.
The special variables are often used in situations where method calls are logged. Exactly which form of the method call needs logging is up to individual requirements, but the example code below shows all the possible expansions, plus how an exception message could be tailored to show the C++ method declaration: %exception Special::something { log("symname: $symname"); log("overname: $overname"); log("wrapname: $wrapname"); log("decl: $decl"); log("fulldecl: $fulldecl"); try { $action } catch (MemoryError) { croak("Out of memory in $decl"); } } void log(const char *message); struct Special { void something(const char *c); void something(int i); };
Below shows the expansions for the 1st of the overloaded log("symname: Special_something"); log("overname: __SWIG_0"); log("wrapname: _wrap_Special_something__SWIG_0"); log("decl: Special::something(char const *)"); log("fulldecl: void Special::something(char const *)"); try { (arg1)->something((char const *)arg2); } catch (MemoryError) { croak("Out of memory in Special::something(char const *)"); } 11.1.7 Using The SWIG exception library
The // Language independent exception handler %include exception.i %exception { try { $action } catch(RangeError) { SWIG_exception(SWIG_ValueError, "Range Error"); } catch(DivisionByZero) { SWIG_exception(SWIG_DivisionByZero, "Division by zero"); } catch(OutOfMemory) { SWIG_exception(SWIG_MemoryError, "Out of memory"); } catch(...) { SWIG_exception(SWIG_RuntimeError,"Unknown exception"); } }
As arguments, SWIG_UnknownError SWIG_IOError SWIG_RuntimeError SWIG_IndexError SWIG_TypeError SWIG_DivisionByZero SWIG_OverflowError SWIG_SyntaxError SWIG_ValueError SWIG_SystemError SWIG_AttributeError SWIG_MemoryError SWIG_NullReferenceError
Since the 11.2 Object ownership and %newobjectA common problem in some applications is managing proper ownership of objects. For example, consider a function like this: Foo *blah() { Foo *f = new Foo(); return f; }
If you wrap the function
To fix this, you can provide an extra hint to the code generator using the %newobject blah; Foo *blah();
%newobject ::blah(); // Only applies to global blah %newobject Object::blah(int,double); // Only blah(int,double) in Object %newobject *::copy; // Copy method in all classes ...
When
Closely related to %typemap(newfree) char * "free($1);"; ... %newobject strdup; ... char *strdup(const char *s);
In this case, the result of the function is a string in the target language. Since this string is a copy of the original result, the data returned by
As a complement to the %newobject create_foo; %delobject destroy_foo; ... Foo *create_foo(); void destroy_foo(Foo *foo); or in a member method as: %delobject Foo::destroy; class Foo { public: void destroy() { delete this;} private: ~Foo(); };
Compatibility note: Previous versions of SWIG had a special %new char *strdup(const char *s); For now this is still supported but is deprecated.
How to shoot yourself in the foot: The %newobject char *strdup(const char *s); The results might not be what you expect. 11.3 Features and the %feature directive
Both %feature("except") Object::allocate { try { $action } catch (MemoryError) { croak("Out of memory"); } } %feature("new","1") *::copy;
In fact, the #define %exception %feature("except") #define %newobject %feature("new","1")
The name matching rules outlined in the Ambiguity resolution and renaming section applies to all /* Define a global exception handler */ %feature("except") { try { $action } ... } ... bunch of declarations ...
The %feature("except") Object::method { $action }; %feature("except") Object::method %{ $action %}; %feature("except") Object::method " $action "; %feature("except","$action") Object::method;
The syntax in the first variation will generate the 11.3.1 Feature attributes
The %feature("name","value", attribute1="AttributeValue1") symbol; %feature("name", attribute1="AttributeValue1") symbol {value}; %feature("name", attribute1="AttributeValue1") symbol %{value%}; %feature("name", attribute1="AttributeValue1") symbol "value";
More than one attribute can be specified using a comma separated list. The Java module is an example that uses attributes in %feature("except", throws="MyExceptionClass") Object::method { try { $action } catch (...) { ... code to throw a MyExceptionClass Java exception ... } }; Further details can be obtained from the Java exception handling section. 11.3.2 Feature flags
Feature flags are used to enable or disable a particular feature. Feature flags are a common but simple usage of %feature("featurename") // enables feature %feature("featurename", "1") // enables feature %feature("featurename", "x") // enables feature %feature("featurename", "0") // disables feature %feature("featurename", "") // clears feature
Actually any value other than zero will enable the feature. Note that if the value is omitted completely, the default value becomes // features are disabled by default int red; // mutable %feature("immutable"); // global enable int orange; // immutable %feature("immutable","0"); // global disable int yellow; // mutable %feature("immutable","1"); // another form of global enable int green; // immutable %feature("immutable",""); // clears the global feature int blue; // mutable Note that features are disabled by default and must be explicitly enabled either globally or by specifying a targeted declaration. The above intersperses SWIG directives with C code. Of course you can target features explicitly, so the above could also be rewritten as: %feature("immutable","1") orange; %feature("immutable","1") green; int red; // mutable int orange; // immutable int yellow; // mutable int green; // immutable int blue; // mutable The above approach allows for the C declarations to be separated from the SWIG directives for when the C declarations are parsed from a C header file. The logic above can of course be inverted and rewritten as: %feature("immutable","1"); %feature("immutable","0") red; %feature("immutable","0") yellow; %feature("immutable","0") blue; int red; // mutable int orange; // immutable int yellow; // mutable int green; // immutable int blue; // mutable
As hinted above for %featurename // equivalent to %feature("featurename", "1") ie enables feature %nofeaturename // equivalent to %feature("featurename", "0") ie disables feature %clearfeaturename // equivalent to %feature("featurename", "") ie clears feature The concept of clearing features is discussed next. 11.3.3 Clearing features
A feature stays in effect until it is explicitly cleared. A feature is cleared by supplying a // Define global exception handler %feature("except") { try { $action } catch (...) { croak("Unknown C++ exception"); } } // Define exception handler for all clone methods to log the method calls %feature("except") *::clone() { try { logger.info("$action"); $action } catch (...) { croak("Unknown C++ exception"); } } ... initial set of class declarations with clone methods ... // clear the previously defined feature %feature("except","") *::clone(); ... final set of class declarations with clone methods ... In the above scenario, the initial set of clone methods will log all method invocations from the target language. This specific feature is cleared for the final set of clone methods. However, these clone methods will still have an exception handler (without logging) as the next best feature match for them is the global exception handler.
Note that clearing a feature is not always the same as disabling it. Clearing the feature above with Note that the feature must match exactly for it to be cleared by any previously defined feature. For example the following attempt to clear the initial feature will not work: %feature("except") clone() { logger.info("$action"); $action } %feature("except","") *::clone(); but this will: %feature("except") clone() { logger.info("$action"); $action } %feature("except","") clone();
SWIG provides macros for disabling and clearing features. Many of these can be found in the #define %exception %feature("except") #define %noexception %feature("except","0") #define %clearexception %feature("except","") 11.3.4 Features and default arguments
SWIG treats methods with default arguments as separate overloaded methods as detailed in the default arguments section. Any %feature("except") void hello(int i=0, double d=0.0) { ... } void hello(int i=0, double d=0.0); will apply the feature to all three wrapper methods, that is: void hello(int i, double d); void hello(int i); void hello(); If the default arguments are not specified in the feature: %feature("except") void hello(int i, double d) { ... } void hello(int i=0, double d=0.0); then the feature will only apply to this wrapper method: void hello(int i, double d); and not these wrapper methods: void hello(int i); void hello(); If compactdefaultargs are being used, then the difference between specifying or not specifying default arguments in a feature is not applicable as just one wrapper is generated. Compatibility note: The different behaviour of features specified with or without default arguments was introduced in SWIG-1.3.23 when the approach to wrapping methods with default arguments was changed. 11.3.5 Feature example
As has been shown earlier, the intended use for the %module example %rename(bar_id) bar(int,double); // Rewrite bar() to allow some nice overloading %feature("shadow") Foo::bar(int) %{ def bar(*args): if len(args) == 3: return apply(examplec.Foo_bar_id,args) return apply(examplec.Foo_bar,args) %} class Foo { public: int bar(int x); int bar(int x, double y); }
Further details of 12 ContractsA common problem that arises when wrapping C libraries is that of maintaining reliability and checking for errors. The fact of the matter is that many C programs are notorious for not providing error checks. Not only that, when you expose the internals of an application as a library, it often becomes possible to crash it simply by providing bad inputs or using it in a way that wasn't intended. This chapter describes SWIG's support for software contracts. In the context of SWIG, a contract can be viewed as a runtime constraint that is attached to a declaration. For example, you can easily attach argument checking rules, check the output values of a function and more. When one of the rules is violated by a script, a runtime exception is generated rather than having the program continue to execute. 12.1 The %contract directiveContracts are added to a declaration using the %contract directive. Here is a simple example: %contract sqrt(double x) { require: x >= 0; ensure: sqrt >= 0; } ... double sqrt(double);
In this case, a contract is being added to the In the above example, we're simply making sure that sqrt() returns a non-negative number (if it didn't, then it would be broken in some way). Once a contract has been specified, it modifies the behavior of the resulting module. For example: >>> example.sqrt(2) 1.4142135623730951 >>> example.sqrt(-2) Traceback (most recent call last): File "<stdin>", line 1, in ? RuntimeError: Contract violation: require: (arg1>=0) >>> 12.2 %contract and classes
The %contract Foo::bar(int x, int y) { require: x > 0; ensure: bar > 0; } %contract Foo::Foo(int a) { require: a > 0; } class Foo { public: Foo(int); int bar(int, int); };
The way in which class Spam : public Foo { public: int bar(int,int); // Gets contract defined for Foo::bar(int,int) }; In addition to this, separate contracts can be applied to both the base class and a derived class. For example: %contract Foo::bar(int x, int) { require: x > 0; } %contract Spam::bar(int, int y) { require: y > 0; } class Foo { public: int bar(int,int); // Gets Foo::bar contract. }; class Spam : public Foo { public: int bar(int,int); // Gets Foo::bar and Spam::bar contract };
When more than one contract is applied, the conditions specified in a “require:” section are combined together using a logical-AND operation. In other words conditions specified for the base class and conditions specified for the derived class all must hold. In the above example, this means that both the arguments to 12.3 Constant aggregation and %aggregate_checkConsider an interface file that contains the following code: #define UP 1 #define DOWN 2 #define RIGHT 3 #define LEFT 4 void move(SomeObject *, int direction, int distance); One thing you might want to do is impose a constraint on the direction parameter to make sure it's one of a few accepted values. To do that, SWIG provides an easy to use macro %aggregate_check() that works like this: %aggregate_check(int, check_direction, UP, DOWN, LEFT, RIGHT); This merely defines a utility function of the form int check_direction(int x); That checks the argument x to see if it is one of the values listed. This utility function can be used in contracts. For example: %aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT); %contract move(SomeObject *, int direction, in) { require: check_direction(direction); } #define UP 1 #define DOWN 2 #define RIGHT 3 #define LEFT 4 void move(SomeObject *, int direction, int distance); Alternatively, it can be used in typemaps and other directives. For example: %aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT); %typemap(check) int direction { if (!check_direction($1)) SWIG_exception(SWIG_ValueError, "Bad direction"); } #define UP 1 #define DOWN 2 #define RIGHT 3 #define LEFT 4 void move(SomeObject *, int direction, int distance); Regrettably, there is no automatic way to perform similar checks with enums values. Maybe in a future release. 12.4 NotesContract support was implemented by Songyan (Tiger) Feng and first appeared in SWIG-1.3.20. 13 Variable Length Arguments(a.k.a, “The horror. The horror.”)
This chapter describes the problem of wrapping functions that take a variable number of arguments. For instance, generating wrappers for the C This topic is sufficiently advanced to merit its own chapter. In fact, support for varargs is an often requested feature that was first added in SWIG-1.3.12. Most other wrapper generation tools have wisely chosen to avoid this issue. 13.1 IntroductionSome C and C++ programs may include functions that accept a variable number of arguments. For example, most programmers are familiar with functions from the C library such as the following: int printf(const char *fmt, ...) int fprintf(FILE *, const char *fmt, ...); int sprintf(char *s, const char *fmt, ...); Although there is probably little practical purpose in wrapping these specific C library functions in a scripting language (what would be the point?), a library may include its own set of special functions based on a similar API. For example: int traceprintf(const char *fmt, ...); In this case, you may want to have some kind of access from the target language.
Before describing the SWIG implementation, it is important to discuss the common uses of varargs that you are likely to encounter in real programs. Obviously, there are the int execlp(const char *path, const char *arg1, ...); ... /* Example */ execlp("ls","ls","-l",NULL);
In addition, varargs is sometimes used to fake default arguments in older C libraries. For instance, the low level int open(const char *path, int oflag, ...); ... /* Examples */ f = open("foo", O_RDONLY); g = open("bar", O_WRONLY | O_CREAT, 0644);
Finally, to implement a varargs function, recall that you have to use the C library functions defined in List make_list(const char *s, ...) { va_list ap; List x; ... va_start(ap, s); while (s) { x.append(s); s = va_arg(ap, const char *); } va_end(ap); return x; } 13.2 The ProblemGenerating wrappers for a variable length argument function presents a number of special challenges. Although C provides support for implementing functions that receive variable length arguments, there are no functions that can go in the other direction. Specifically, you can't write a function that dynamically creates a list of arguments and which invokes a varargs function on your behalf.
Although it is possible to write functions that accept the special type The reason this doesn't work has to do with the way that function calls get compiled. For example, suppose that your program has a function call like this: printf("Hello %s. Your number is %d\n", name, num);
When the compiler looks at this, it knows that you are calling
In contrast, suppose you attempted to make some kind of wrapper around int wrap_printf(const char *fmt, ...) { va_list ap; va_start(ap,fmt); ... printf(fmt,ap); ... va_end(ap); };
Although this code might compile, it won't do what you expect. This is because the call to Unfortunately, the situation just described is exactly the problem faced by wrapper generation tools. In general, the number of passed arguments will not be known until run-time. To make matters even worse, you won't know the types and sizes of arguments until run-time as well. Needless to say, there is no obvious way to make the C compiler generate code for a function call involving an unknown number of arguments of unknown types. In theory, it is possible to write a wrapper that does the right thing. However, this involves knowing the underlying ABI for the target platform and language as well as writing special purpose code that manually constructed the call stack before making a procedure call. Unfortunately, both of these tasks require the use of inline assembly code. Clearly, that's the kind of solution you would much rather avoid. With this nastiness in mind, SWIG provides a number of solutions to the varargs wrapping problem. Most of these solutions are compromises that provide limited varargs support without having to resort to assembly language. However, SWIG can also support real varargs wrapping (with stack-frame manipulation) if you are willing to get hands dirty. Keep reading. 13.3 Default varargs supportWhen variable length arguments appear in an interface, the default behavior is to drop the variable argument list entirely, replacing them with a single NULL pointer. For example, if you had this function, void traceprintf(const char *fmt, ...); it would be wrapped as if it had been declared as follows: void traceprintf(const char *fmt); When the function is called inside the wrappers, it is called as follows: traceprintf(arg1, NULL); Arguably, this approach seems to defeat the whole point of variable length arguments. However, this actually provides enough support for many simple kinds of varargs functions to still be useful. For instance, you could make function calls like this (in Python): >>> traceprintf("Hello World") >>> traceprintf("Hello %s. Your number is %d\n" % (name, num)) Notice how string formatting is being done in Python instead of C. 13.4 Argument replacement using %varargs
Instead of dropping the variable length arguments, an alternative approach is to replace %varargs(int mode = 0) open; ... int open(const char *path, int oflags, ...); is equivalent to this: int open(const char *path, int oflags, int mode = 0);
In this case, %varargs(10,char *arg = NULL) execlp; ... int execlp(const char *path, const char *arg1, ...);
This would wrap
Argument replacement is most appropriate in cases where the types of the extra arguments is uniform and the maximum number of arguments is known. When replicated argument replacement is used, at least one extra argument is added to the end of the arguments when making the function call. This argument serves as a sentinel to make sure the list is properly terminated. It has the same value as that supplied to the
Argument replacement is not as useful when working with functions that accept mixed argument types such as 13.5 Varargs and typemapsVariable length arguments may be used in typemap specifications. For example: %typemap(in) (...) { // Get variable length arguments (somehow) ... } %typemap(in) (const char *fmt, ...) { // Multi-argument typemap }
However, this immediately raises the question of what “type” is actually used to represent
To illustrate, here is a safer version of wrapping %typemap(in) (const char *fmt, ...) { $1 = "%s"; /* Fix format string to %s */ $2 = (void *) PyString_AsString($input); /* Get string argument */ }; ... int printf(const char *fmt, ...);
In this example, the format string is implicitly set to wrap_printf() { char *arg1; void *arg2; int result; arg1 = "%s"; arg2 = (void *) PyString_AsString(arg2obj); ... result = printf(arg1,arg2); ... } Notice how both arguments are passed to the function and it does what you would expect. The next example illustrates a more advanced kind of varargs typemap. Disclaimer: this requires special support in the target language module and is not guaranteed to work with all SWIG modules at this time. It also starts to illustrate some of the more fundamental problems with supporting varargs in more generality.
If a typemap is defined for any form of %typemap(in) (...)(char *args[10]) { int i; int argc; for (i = 0; i < 10; i++) args[i] = 0; argc = PyTuple_Size(varargs); if (argc > 10) { PyErr_SetString(PyExc_ValueError,"Too many arguments"); return NULL; } for (i = 0; i < argc; i++) { PyObject *o = PyTuple_GetItem(varargs,i); if (!PyString_Check(o)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); return NULL; } args[i] = PyString_AsString(o); } $1 = (void *) args; }
In this typemap, the special variable %feature("action") execlp { char *args = (char **) arg3; result = execlp(arg1, arg2, args[0], args[1], args[2], args[3], args[4], args[5],args[6],args[7],args[8],args[9], NULL); } int execlp(const char *path, const char *arg, ...); This patches everything up and creates a function that more or less works. However, don't try explaining this to your coworkers unless you know for certain that they've had several cups of coffee. If you really want to elevate your guru status and increase your job security, continue to the next section. 13.6 Varargs wrapping with libffiAll of the previous examples have relied on features of SWIG that are portable and which don't rely upon any low-level machine-level details. In many ways, they have all dodged the real issue of variable length arguments by recasting a varargs function into some weaker variation with a fixed number of arguments of known types. In many cases, this works perfectly fine. However, if you want more generality than this, you need to bring out some bigger guns. One way to do this is to use a special purpose library such as libffi ( http://sources.redhat.com/libffi). libffi is a library that allows you to dynamically construct call-stacks and invoke procedures in a relatively platform independent manner. Details about the library can be found in the libffi distribution and are not repeated here.
To illustrate the use of libffi, suppose that you really wanted to create a wrapper for /* Take an arbitrary number of extra arguments and place into an array of strings */ %typemap(in) (...) { char **argv; int argc; int i; argc = PyTuple_Size(varargs); argv = (char **) malloc(sizeof(char *)*(argc+1)); for (i = 0; i < argc; i++) { PyObject *o = PyTuple_GetItem(varargs,i); if (!PyString_Check(o)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); free(argv); return NULL; } argv[i] = PyString_AsString(o); } argv[i] = NULL; $1 = (void *) argv; } /* Rewrite the function call, using libffi */ %feature("action") execlp { int i, vc; ffi_cif cif; ffi_type **types; void **values; char **args; vc = PyTuple_Size(varargs); types = (ffi_type **) malloc((vc+3)*sizeof(ffi_type *)); values = (void **) malloc((vc+3)*sizeof(void *)); args = (char **) arg3; /* Set up path parameter */ types[0] = &ffi_type_pointer; values[0] = &arg1; /* Set up first argument */ types[1] = &ffi_type_pointer; values[1] = &arg2; /* Set up rest of parameters */ for (i = 0; i <= vc; i++) { types[2+i] = &ffi_type_pointer; values[2+i] = &args[i]; } if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+3, &ffi_type_uint, types) == FFI_OK) { ffi_call(&cif, (void (*)()) execlp, &result, values); } else { PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); free(types); free(values); free(arg3); return NULL; } free(types); free(values); free(arg3); } /* Declare the function. Whew! */ int execlp(const char *path, const char *arg1, ...); Looking at this example, you may start to wonder if SWIG is making life any easier. Given the amount of code involved, you might also wonder why you didn't just write a hand-crafted wrapper! Either that or you're wondering “why in the hell am I trying to wrap this varargs function in the first place?!?” Obviously, those are questions you'll have to answer for yourself.
As a more extreme example of libffi, here is some code that attempts to wrap /* A wrapper for printf() using libffi */ %{ /* Structure for holding passed arguments after conversion */ typedef struct { int type; union { int ivalue; double dvalue; void *pvalue; } val; } vtype; enum { VT_INT, VT_DOUBLE, VT_POINTER }; %} %typemap(in) (const char *fmt, ...) { vtype *argv; int argc; int i; /* Format string */ $1 = PyString_AsString($input); /* Variable length arguments */ argc = PyTuple_Size(varargs); argv = (vtype *) malloc(argc*sizeof(vtype)); for (i = 0; i < argc; i++) { PyObject *o = PyTuple_GetItem(varargs,i); if (PyInt_Check(o)) { argv[i].type = VT_INT; argv[i].val.ivalue = PyInt_AsLong(o); } else if (PyFloat_Check(o)) { argv[i].type = VT_DOUBLE; argv[i].val.dvalue = PyFloat_AsDouble(o); } else if (PyString_Check(o)) { argv[i].type = VT_POINTER; argv[i].val.pvalue = (void *) PyString_AsString(o); } else { PyErr_SetString(PyExc_ValueError,"Unsupported argument type"); free(argv); return NULL; } } $2 = (void *) argv; } /* Rewrite the function call using libffi */ %feature("action") printf { int i, vc; ffi_cif cif; ffi_type **types; void **values; vtype *args; vc = PyTuple_Size(varargs); types = (ffi_type **) malloc((vc+1)*sizeof(ffi_type *)); values = (void **) malloc((vc+1)*sizeof(void *)); args = (vtype *) arg2; /* Set up fmt parameter */ types[0] = &ffi_type_pointer; values[0] = &arg1; /* Set up rest of parameters */ for (i = 0; i < vc; i++) { switch(args[i].type) { case VT_INT: types[1+i] = &ffi_type_uint; values[1+i] = &args[i].val.ivalue; break; case VT_DOUBLE: types[1+i] = &ffi_type_double; values[1+i] = &args[i].val.dvalue; break; case VT_POINTER: types[1+i] = &ffi_type_pointer; values[1+i] = &args[i].val.pvalue; break; default: abort(); /* Whoa! We're seriously hosed */ break; } } if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+1, &ffi_type_uint, types) == FFI_OK) { ffi_call(&cif, (void (*)()) printf, &result, values); } else { PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); free(types); free(values); free(args); return NULL; } free(types); free(values); free(args); } /* The function */ int printf(const char *fmt, ...); Much to your amazement, it even seems to work if you try it: >>> import example >>> example.printf("Grade: %s %d/60 = %0.2f%%\n", "Dave", 47, 47.0*100/60) Grade: Dave 47/60 = 78.33% >>> Of course, there are still some limitations to consider: >>> example.printf("la de da de da %s", 42) Segmentation fault (core dumped)
And, on this note, we leave further exploration of libffi to the reader as an exercise. Although Python has been used as an example, most of the techniques in this section can be extrapolated to other language modules with a bit of work. The only details you need to know is how the extra arguments are accessed in each target language. For example, in the Python module, we used the special 13.7 Wrapping of va_list
Closely related to variable length argument wrapping, you may encounter functions that accept a parameter of type int vfprintf(FILE *f, const char *fmt, va_list ap);
As far as we know, there is no obvious way to wrap these functions with SWIG. This is because there is no documented way to assemble the proper va_list structure (there are no C library functions to do it and the contents of va_list are opaque). Not only that, the contents of a 13.8 C++ Issues
Wrapping of C++ member functions that accept a variable number of arguments presents a number of challenges. By far, the easiest way to handle this is to use the %varargs (10, char * = NULL) Foo::bar; class Foo { public: virtual void bar(char *arg, ...); // gets varargs above }; class Spam: public Foo { public: virtual void bar(char *arg, ...); // gets varargs above };
Doing anything more advanced than this is likely to involve a serious world of pain. In order to use a library like libffi, you will need to know the underlying calling conventions and details of the C++ ABI. For instance, the details of how
If you do decide to change the underlying action code, be aware that SWIG always places the %feature("action") Foo::bar { ... result = arg1->bar(arg2, arg3, etc.); ... } Given the potential to shoot yourself in the foot, it is probably easier to reconsider your design or to provide an alternative interface using a helper function than it is to create a fully general wrapper to a varargs C++ member function. 13.9 Discussion
This chapter has provided a number of techniques that can be used to address the problem of variable length argument wrapping. If you care about portability and ease of use, the One point of discussion concerns the structure of the libffi examples in the previous section. Looking at that code, it is not at all clear that this is the easiest way to solve the problem. However, there are a number of subtle aspects of the solution to consider–mostly concerning the way in which the problem has been decomposed. First, the example is structured in a way that tries to maintain separation between wrapper-specific information and the declaration of the function itself. The idea here is that you might structure your interface like this: %typemap(const char *fmt, ...) { ... } %feature("action") traceprintf { ... } /* Include some header file with traceprintf in it */ %include "someheader.h"
Second, careful scrutiny will reveal that the typemaps involving #ifdef USE_LIBFFI %feature("action") printf { ... } #endif #ifdef USE_OTHERFFI %feature("action") printf { ... } #endif Finally, even though you might be inclined to just write a hand-written wrapper for varargs functions, the techniques used in the previous section have the advantage of being compatible with all other features of SWIG such as exception handling. As a final word, some C programmers seem to have the assumption that the wrapping of variable length argument functions is an easily solved problem. However, this section has hopefully dispelled some of these myths. All things being equal, you are better off avoiding variable length arguments if you can. If you can't avoid them, please consider some of the simple solutions first. If you can't live with a simple solution, proceed with caution. At the very least, make sure you carefully read the section “A7.3.2 Function Calls” in Kernighan and Ritchie and make sure you fully understand the parameter passing conventions used for varargs. Also, be aware of the platform dependencies and reliability issues that this will introduce. Good luck. 14 Warning Messages14.1 IntroductionDuring compilation, SWIG may generate a variety of warning messages. For example: example.i:16: Warning(501): Overloaded declaration ignored. bar(double) example.i:15: Warning(501): Previous declaration is bar(int) Typically, warning messages indicate non-fatal problems with the input where the generated wrapper code will probably compile, but it may not work like you expect. 14.2 Warning message suppression
All warning messages have a numeric code that is shown in the warning message itself. To suppress the printing of a warning message, a number of techniques can be used. First, you can run SWIG with the % swig -python -w501 example.i % swig -python -w501,505,401 example.i Alternatively, warnings can be suppressed by inserting a special preprocessor pragma into the input file: %module example #pragma SWIG nowarn=501 #pragma SWIG nowarn=501,505,401
Finally, code-generation warnings can be disabled on a declaration by declaration basis using the %module example %warnfilter(501) foo; ... int foo(int); int foo(double); // Silently ignored.
The %warnfilter(501) Object::foo; class Object { public: int foo(int); int foo(double); // Silently ignored ... }; class Derived : public Object { public: int foo(int); int foo(double); // Silently ignored ... }; Warnings can be suppressed for an entire class by supplying a class name. For example: %warnfilter(501) Object; class Object { public: ... // All 501 warnings ignored in class }; There is no option to suppress all SWIG warning messages. The warning messages are there for a reason—to tell you that something may be broken in your interface. Ignore the warning messages at your own peril. 14.3 Enabling extra warnings
Some warning messages are disabled by default and are generated only to provide additional diagnostics. These warnings can be turned on using the % swig -Wextra -python example.i To selectively turn on extra warning messages, you can use the directives and options in the previous section–simply add a “+” to all warning numbers. For example: % swig -w+309,+452 example.i or in your interface file use either #pragma SWIG nowarn=+309,+452 or %warnfilter(+309,+452) foo;
Note: selective enabling of warnings with You can of course also enable all warnings and suppress a select few, for example: % swig -Wextra -w309,452 example.i
The warnings on the right take precedence over the warnings on the left, so in the above example
If you would like all warnings to appear, regardless of the warning filters used, then use the 14.4 Issuing a warning message
Warning messages can be issued from an interface file using a number of directives. The %warn "900:This is your last warning!" All warning messages are optionally prefixed by the warning number to use. If you are generating your own warnings, make sure you don't use numbers defined in the table at the end of this section.
The %ignorewarn("362:operator= ignored") operator=;
Warning messages can be associated with typemaps using the %typemap(in, warning="901:You are really going to regret this") blah * { ... } In this case, the warning message will be printed whenever the typemap is actually used. 14.5 Symbolic symbols
The %define SWIGWARN_TYPE_UNDEFINED_CLASS 401 %enddef
so #pragma SWIG nowarn=SWIGWARN_TYPE_UNDEFINED_CLASS or %warnfilter(SWIGWARN_TYPE_UNDEFINED_CLASS) Foo; 14.6 CommentaryThe ability to suppress warning messages is really only provided for advanced users and is not recommended in normal use. You are advised to modify your interface to fix the problems highlighted by the warnings wherever possible instead of suppressing warnings. Certain types of SWIG problems are errors. These usually arise due to parsing errors (bad syntax) or semantic problems for which there is no obvious recovery. There is no mechanism for suppressing error messages. 14.7 Warnings as errors
Warnings can be handled as errors by using the 14.8 Message output formatThe output format for both warnings and errors can be selected for integration with your favourite IDE/editor. Editors and IDEs can usually parse error messages and if in the appropriate format will easily take you directly to the source of the error. The standard format is used by default except on Windows where the Microsoft format is used by default. These can be overridden using command line options, for example: $ swig -python -Fstandard example.i example.i:4: Syntax error in input. $ swig -python -Fmicrosoft example.i example.i(4): Syntax error in input. 14.9 Warning number reference14.9.1 Deprecated features (100-199)
14.9.2 Preprocessor (200-299)
14.9.3 C/C++ Parser (300-399)
14.9.4 Types and typemaps (400-499)
14.9.5 Code generation (500-599)
14.9.6 Language module specific (800-899)
14.9.7 User defined (900-999)These numbers can be used by your own application. 14.10 HistoryThe ability to control warning messages was first added to SWIG-1.3.12. 15 Working with Modules15.1 Modules IntroductionEach invocation of SWIG requires a module name to be specified. The module name is used to name the resulting target language extension module. Exactly what this means and and what the name is used for depends on the target language, for example the name can define a target language namespace or merely be a useful name for naming files or helper classes. Essentially, a module comprises target language wrappers for a chosen collection of global variables/functions, structs/classes and other C/C++ types.
The module name can be supplied in one of two ways. The first is to specify it with the special %module(option1="value1",option2="value2",...) modulename where the modulename is mandatory and the options add one or more optional additional features. Typically no options are specified, for example: %module mymodule
The second way to specify the module name is with the When first working with SWIG, users commonly start by creating a single module. That is, you might define a single SWIG interface that wraps some set of C/C++ code. You then compile all of the generated wrapper code together and use it. For large applications, however, this approach is problematic—the size of the generated wrapper code can be rather large. Moreover, it is probably easier to manage the target language interface when it is broken up into smaller pieces. This chapter describes the problem of using SWIG in programs where you want to create a collection of modules. Each module in the collection is created via separate invocations of SWIG. 15.2 BasicsThe basic usage case with multiple modules is when modules do not have cross-references (ie. when wrapping multiple independent C APIs). In that case, swig input files should just work out of the box - you simply create multiple wrapper .cxx files, link them into your application, and insert/load each in the scripting language runtime as you would do for the single module case. A bit more complex is the case in which modules need to share information. For example, when one module extends the class of another by deriving from it: // File: base.h class base { public: int foo(); };
// File: base_module.i %module base_module %{ #include "base.h" %} %include "base.h"
// File: derived_module.i %module derived_module %import "base_module.i" %inline %{ class derived : public base { public: int bar(); }; %}
To create the wrapper properly, module derived_module.i:8: Warning(401): Base class 'base' ignored - unknown module name for base. Either import the appropriate module interface file or specify the name of the module in the %import directive.
It is sometimes desirable to import the header file rather than the interface file and overcome the above warning. For example in the case of the imported interface being quite large, it may be desirable to simplify matters and just import a small header file of dependent types. This can be done by specifying the optional // File: derived_module.i %module derived_module %import(module="base_module") "base.h" %inline %{ class derived : public base { public: int bar(); };
Note that “base_module” is the module name and is the same as that specified in Another issue to beware of is that multiple dependent wrappers should not be linked/loaded in parallel from multiple threads as SWIG provides no locking - for more on that issue, read on. 15.3 The SWIG runtime codeMany of SWIG's target languages generate a set of functions commonly known as the “SWIG runtime.” These functions are primarily related to the runtime type system which checks pointer types and performs other tasks such as proper casting of pointer values in C++. As a general rule, the statically typed target languages, such as Java, use the language's built in static type checking and have no need for a SWIG runtime. All the dynamically typed / interpreted languages rely on the SWIG runtime. The runtime functions are private to each SWIG-generated module. That is, the runtime functions are declared with “static” linkage and are visible only to the wrapper functions defined in that module. The only problem with this approach is that when more than one SWIG module is used in the same application, those modules often need to share type information. This is especially true for C++ programs where SWIG must collect and share information about inheritance relationships that cross module boundaries. To solve the problem of sharing information across modules, a pointer to the type information is stored in a global variable in the target language namespace. During module initialization, type information is loaded into the global data structure of type information from all modules. There are a few trade offs with this approach. This type information is global across all SWIG modules loaded, and can cause type conflicts between modules that were not designed to work together. To solve this approach, the SWIG runtime code uses a define SWIG_TYPE_TABLE to provide a unique type table. This behavior can be enabled when compiling the generated _wrap.cxx or _wrap.c file by adding -DSWIG_TYPE_TABLE=myprojectname to the command line argument. Then, only modules compiled with SWIG_TYPE_TABLE set to myprojectname will share type information. So if your project has three modules, all three should be compiled with -DSWIG_TYPE_TABLE=myprojectname, and then these three modules will share type information. But any other project's types will not interfere or clash with the types in your module. Another issue relating to the global type table is thread safety. If two modules try and load at the same time, the type information can become corrupt. SWIG currently does not provide any locking, and if you use threads, you must make sure that modules are loaded serially. Be careful if you use threads and the automatic module loading that some scripting languages provide. One solution is to load all modules before spawning any threads, or use SWIG_TYPE_TABLE to separate type tables so they do not clash with each other. Lastly, SWIG uses a #define SWIG_RUNTIME_VERSION, located in Lib/swigrun.swg and near the top of every generated module. This number gets incremented when the data structures change, so that SWIG modules generated with different versions can peacefully coexist. So the type structures are separated by the (SWIG_TYPE_TABLE, SWIG_RUNTIME_VERSION) pair, where by default SWIG_TYPE_TABLE is empty. Only modules compiled with the same pair will share type information. 15.4 External access to the runtime
As described in The run-time type checker, the functions $ swig -python -external-runtime <filename>
The filename argument is optional and if it is not passed, then the default filename will be something like Inside this header the functions are declared static and are included inline into the file, and thus the file does not need to be linked against any SWIG libraries or code (you might still need to link against the language libraries like libpython-2.3). Data is shared between this file and the _wrap.c files through a global variable in the scripting language. It is also possible to copy this header file along with the generated wrapper files into your own package, so that you can distribute a package that can be compiled without SWIG installed (this works because the header file is self-contained, and does not need to link with anything). This header will also use the -DSWIG_TYPE_TABLE described above, so when compiling any code which includes the generated header file should define the SWIG_TYPE_TABLE to be the same as the module whose types you are trying to access. 15.5 A word of caution about static libraries
When working with multiple SWIG modules, you should take care not to use static libraries. For example, if you have a static library 15.6 ReferencesDue to the complexity of working with shared libraries and multiple modules, it might be a good idea to consult an outside reference. John Levine's “Linkers and Loaders” is highly recommended. 15.7 Reducing the wrapper file size
Using multiple modules with the
-fcompact
-fvirtual struct Base { virtual void method(); ... }; struct Derived : Base { virtual void method(); ... };
Normally wrappers are generated for both methods, whereas this command line option will suppress the generation of a wrapper for
%feature(“compactdefaultargs”) 16 Using SWIG with ccache - ccache-swig(1) manpage16.1 NAMEccache-swig - a fast compiler cache 16.2 SYNOPSISccache-swig [OPTION] ccache-swig <compiler> [COMPILER OPTIONS] <compiler> [COMPILER OPTIONS] 16.3 DESCRIPTIONccache-swig is a compiler cache. It speeds up re-compilation of C/C++/SWIG code by caching previous compiles and detecting when the same compile is being done again. ccache-swig is ccache plus support for SWIG. ccache and ccache-swig are used interchangeably in this document. 16.4 OPTIONS SUMMARYHere is a summary of the options to ccache-swig. -s show statistics summary -z zero statistics -c run a cache cleanup -C clear the cache completely -F <n> set maximum files in cache -M <n> set maximum size of cache (use G, M or K) -h this help page -V print version number 16.5 OPTIONSThese options only apply when you invoke ccache as “ccache-swig”. When invoked as a compiler none of these options apply. In that case your normal compiler options apply and you should refer to your compilers documentation.
16.6 INSTALLATIONThere are two ways to use ccache. You can either prefix your compile commands with “ccache-swig” or you can create a symbolic link between ccache-swig and the names of your compilers. The first method is most convenient if you just want to try out ccache or wish to use it for some specific projects. The second method is most useful for when you wish to use ccache for all your compiles. To install for usage by the first method just copy ccache-swig to somewhere in your path. To install for the second method do something like this: cp ccache-swig /usr/local/bin/ ln -s /usr/local/bin/ccache-swig /usr/local/bin/gcc ln -s /usr/local/bin/ccache-swig /usr/local/bin/g++ ln -s /usr/local/bin/ccache-swig /usr/local/bin/cc ln -s /usr/local/bin/ccache-swig /usr/local/bin/swig This will work as long as /usr/local/bin comes before the path to gcc (which is usually in /usr/bin). After installing you may wish to run “which gcc” to make sure that the correct link is being used. Note! Do not use a hard link, use a symbolic link. A hardlink will cause “interesting” problems. 16.7 EXTRA OPTIONSWhen run as a compiler front end ccache usually just takes the same command line options as the compiler you are using. The only exception to this is the option '–ccache-skip'. That option can be used to tell ccache that the next option is definitely not a input filename, and should be passed along to the compiler as-is. The reason this can be important is that ccache does need to parse the command line and determine what is an input filename and what is a compiler option, as it needs the input filename to determine the name of the resulting object file (among other things). The heuristic ccache uses in this parse is that any string on the command line that exists as a file is treated as an input file name (usually a C file). By using –ccache-skip you can force an option to not be treated as an input file name and instead be passed along to the compiler as a command line option. 16.8 ENVIRONMENT VARIABLESccache uses a number of environment variables to control operation. In most cases you won't need any of these as the defaults will be fine.
16.9 CACHE SIZE MANAGEMENTBy default ccache has a one gigabyte limit on the cache size and no maximum number of files. You can set a different limit using the “ccache -M” and “ccache -F” options, which set the size and number of files limits. When these limits are reached ccache will reduce the cache to 20% below the numbers you specified in order to avoid doing the cache clean operation too often. 16.10 CACHE COMPRESSIONBy default on most platforms ccache will compress all files it puts into the cache using the zlib compression. While this involves a negligible performance slowdown, it significantly increases the number of files that fit in the cache. You can turn off compression setting the CCACHE_NOCOMPRESS environment variable. 16.11 HOW IT WORKSThe basic idea is to detect when you are compiling exactly the same code a 2nd time and use the previously compiled output. You detect that it is the same code by forming a hash of:
These are hashed using md4 (a strong hash) and a cache file is formed based on that hash result. When the same compilation is done a second time ccache is able to supply the correct compiler output (including all warnings etc) from the cache. ccache has been carefully written to always produce exactly the same compiler output that you would get without the cache. If you ever discover a case where ccache changes the output of your compiler then please let me know. 16.12 USING CCACHE WITH DISTCCdistcc is a very useful program for distributing compilation across a range of compiler servers. It is often useful to combine distcc with ccache, so that compiles that are done are sped up by distcc, but that ccache avoids the compile completely where possible. To use distcc with ccache I recommend using the CCACHE_PREFIX option. You just need to set the environment variable CCACHE_PREFIX to 'distcc' and ccache will prefix the command line used with the compiler with the command 'distcc'. 16.13 SHARING A CACHEA group of developers can increase the cache hit rate by sharing a cache directory. The hard links however cause unwanted side effects, as all links to a cached file share the file's modification timestamp. This results in false dependencies to be triggered by timestamp-based build systems whenever another user links to an existing file. Typically, users will see that their libraries and binaries are relinked without reason. To share a cache without side effects, the following conditions need to be met:
16.14 HISTORYccache was inspired by the compilercache shell script script written by Erik Thiele and I would like to thank him for an excellent piece of work. See http://www.erikyyy.de/compilercache/ for the Erik's scripts. ccache-swig is a port of the original ccache with support added for use with SWIG. I wrote ccache because I wanted to get a bit more speed out of a compiler cache and I wanted to remove some of the limitations of the shell-script version. 16.15 DIFFERENCES FROM COMPILERCACHEThe biggest differences between Erik's compilercache script and ccache are:
16.16 CREDITSThanks to the following people for their contributions to ccache
16.17 AUTHORccache was written by Andrew Tridgell http://samba.org/~tridge/. ccache was adapted to create ccache-swig for use with SWIG by William Fulton. If you wish to report a problem or make a suggestion then please email the SWIG developers on the swig-devel mailing list, see http://www.swig.org/mail.html ccache is released under the GNU General Public License version 2 or later. Please see the file COPYING for license details. 17 SWIG and Allegro Common LispThis chapter describes SWIG's support of Allegro Common Lisp. Allegro CL is a full-featured implementation of the Common Lisp language standard that includes many vendor-specific enhancements and add-on modules for increased usability. One such module included in Allegro CL is the Foreign Functions Interface (FFI). This module, tailored primarily toward interfacing with C/C++ and, historically, Fortran, provides a means by which compiled foreign code can be loaded into a running lisp environment and executed. The interface supports the calling of foreign functions and methods, allows for executing lisp routines from foreign code (callbacks), and the passing of data between foreign and lisp code. The goal of this module is to make it possible to quickly generate the necessary foreign function definitions so one can make use of C/C++ foreign libraries directly from lisp without the tedium of having to code them by hand. When necessary, it will also generate further C/C++ code that will need to be linked with the intended library for proper interfacing from lisp. It has been designed with an eye toward flexibility. Some foreign function calls may release the heap, while other should not. Some foreign functions should automatically convert lisp strings into native strings, while others should not. These adjustments and many more are possible with the current module. It is significant to note that, while this is a vendor-specific module, we would like to acknowledge the current and ongoing work by developers in the open source lisp community that are working on similar interfaces to implementation-independent foreign function interfaces (UFFI or CFFI, for example). Such work can only benefit the lisp community, and we would not be unhappy to see some enterprising folk use this work to add to it. 17.1 Basics17.1.1 Running SwigIf you're reading this, you must have some library you need to generate an interface for. In order for SWIG to do this work, however, it needs a bit of information about how it should go about creating your interface, and what you are interfacing to.
SWIG expects a description of what in the foreign interface you wish to connect to. It must consisting of C/C++ declarations and special SWIG directives. SWIG can be furnished with a header file, but an interface can also be generated without library headers by supplying a simple text file–called the interface file, which is typically named with a Note that SWIG does not require any function definitions; the declarations of those functions is all that is necessary. Be careful when tuning the interface as it is quite possible to generate code that will not load or compile. An example interface file is shown below. It makes use of two SWIG directives, one of which requests that the declarations in a header file be used to generate part of the interface, and also includes an additional declaration to be added. example.i %module example %include "header.h" int fact(int n); The contents of header.h are very simple: header.h int fact(char *statement); // pass it a fact, and it will rate it. The contents of example.cl will look like this: example.cl (defpackage :example (:use :common-lisp :swig :ff :excl)) ... helper routines for defining the interface ... (swig-in-package ()) (swig-defun ("fact") ((PARM0_statement cl:string (* :char) )) (:returning (:int ) :strings-convert t) (let ((SWIG_arg0 PARM0_statement)) (swig-ff-call SWIG_arg0))) (swig-defun ("fact") ((PARM0_n cl:integer :int )) (:returning (:int ) :strings-convert t) (let ((SWIG_arg0 PARM0_n)) (swig-ff-call SWIG_arg0))) (swig-dispatcher ("fact" :type :function :arities (1))) The generated file contains calls to internal swig helper functions. In this case there are two calls to swig-defun. These calls will expand into code that will make the appropriate definitions using the Allegro FFI. Note also, that this code is erroneous. Function overloading is not supported in C, and this code will not compile even though SWIG did not complain.
In order to generate a C interface to Allegro CL using this code run swig using the % swig -allegrocl example.i
When building an interface to C++ code, include the % swig -allegrocl -c++ example.i
As a result of running one of the above commands, a file named It is possible to disable the creation of the .cxx file when generating a C interface by using the -nocwrap command-line argument. For interfaces that don't contain complex enum or constant expressions, contain nested struct/union declarations, or doesn't need to use many of the SWIG customization featuers, this will result in a more streamlined, direct interface to the intended module. The generated wrapper file is below. It contains very simple wrappers by default, that simply pass the arguments to the actual function. example_wrap.i ... lots of SWIG internals ... EXPORT int ACL___fact__SWIG_0 (char *larg1) { int lresult = (int)0 ; char *arg1 = (char *) 0 ; int result; arg1 = larg1; try { result = (int)fact(arg1); lresult = result; return lresult; } catch (...) { return (int)0; } } EXPORT int ACL___fact__SWIG_1 (int larg1) { int lresult = (int)0 ; int arg1 ; int result; arg1 = larg1; try { result = (int)fact(arg1); lresult = result; return lresult; } catch (...) { return (int)0; } } And again, the generated lisp code. Note that it differs from what is generated when parsing C code: ... (swig-in-package ()) (swig-defmethod ("fact" "ACL___fact__SWIG_0" :type :function :arity 1) ((PARM0_statement cl:string (* :char) )) (:returning (:int ) :strings-convert t) (let ((SWIG_arg0 PARM0_statement)) (swig-ff-call SWIG_arg0))) (swig-defmethod ("fact" "ACL___fact__SWIG_1" :type :function :arity 1) ((PARM0_n cl:integer :int )) (:returning (:int ) :strings-convert t) (let ((SWIG_arg0 PARM0_n)) (swig-ff-call SWIG_arg0))) (swig-dispatcher ("fact" :type :function :arities (1))) In this case, the interface generates two swig-defmethod forms and a swig-dispatcher form. This provides a single functional interface for all overloaded routines. A more detailed description of this features is to be found in the section titled Function overloading/Parameter defaulting. In order to load a C++ interface, you will need to build a shared library from example_wrap.cxx. Be sure to link in the actual library you created the interface for, as well as any other dependent shared libraries. For example, if you intend to be able to call back into lisp, you will also need to link in the Allegro shared library. The library you create from the C++ wrapper will be what you then load into Allegro CL. 17.1.2 Command Line OptionsThere are three Allegro CL specific command-line option: swig -allegrocl [ options ] filename -identifier-converter [name] - Binds the variable swig:*swig-identifier-convert* in the generated .cl file to name. This function is used to generate symbols for the lisp side of the interface. -cwrap - [default] Generate a .cxx file containing C wrapper function when wrapping C code. The interface generated is similar to what is done for C++ code. -nocwrap - Explicitly turn off generation of .cxx wrappers for C code. Reasonable for modules with simple interfaces. Can not handle all legal enum and constant constructs, or take advantage of SWIG customization features. -isolate - With this command-line argument, all lisp helper functions are defined in a unique package named swig.<module-name> rather than swig. This prevents conflicts when the module is intended to be used with other swig generated interfaces that may, for instance, make use of different identifier converters. See Section 17.5 Identifier converter functions for more details. 17.1.3 Inserting user code into generated files
It is often necessary to include user-defined code into the automatically generated interface files. For example, when building a C++ interface, example_wrap.cxx will likely not compile unless you add a %module example %{ #include "header.h" %} %include "header.h" int fact(int n); Additional sections have been added for inserting into the generated lisp interface file
Note that the block 17.2 Wrapping OverviewNew users to SWIG are encouraged to read SWIG Basics , and SWIG and C++, for those interested in generating an interface to C++. 17.2.1 Function WrappingWriting lisp code that directly invokes functions at the foreign function interface level can be cumbersome. Data must often be translated between lisp and foreign types, data extracted from objects, foreign objects allocated and freed upon completion of the foreign call. Dealing with pointers can be unwieldy when it comes to keeping them distinct from other valid integer values. We make an attempt to ease some of these burdens by making the interface to foreign code much more lisp-like, rather than C like. How this is done is described in later chapters. The layers themselves, appear as follows: ______________ | | (foreign side) | Foreign Code | What we're generating an interface to. |______________| | | _______v______ | | (foreign side) | Wrapper code | extern "C" wrappers calling C++ |______________| functions and methods. | . . . - - + - - . . . _______v______ | | (lisp side) | FFI Layer | Low level lisp interface. ff:def-foreign-call, |______________| ff:def-foreign-variable | +---------------------------- _______v______ _______v______ | | | | (lisp side) | Defuns | | Defmethods | wrapper for overloaded |______________| |______________| functions or those with (lisp side) | defaulted arguments Wrapper for non-overloaded | functions and methods _______v______ | | (lisp side) | Defuns | dispatch function |______________| to overloads based on arity 17.2.2 Foreign WrappersThese wrappers are as generated by SWIG default. The types of function parameters can be transformed in place using the CTYPE typemap. This is use for converting pass-by-value parameters to pass-by-reference where necessary. All wrapper parameters are then bound to local variables for possible transformation of values (see LIN typemap). Return values can be transformed via the OUT typemap. 17.2.3 FFI Wrappers
These are the generated ff:def-foreign-call forms. No typemaps are applicable to this layer, but the ffargs.i: %module ffargs %ffargs(strings_convert="nil",call_direct="t") foo; %ffargs(strings_convert="nil",release_heap=":never",optimize_for_space="t") bar; int foo(float f1, float f2); int foo(float f1, char c2); void bar(void *lisp_fn); char *xxx(); Generates: ffargs.cl: (swig-in-package ()) (swig-defmethod ("foo" "ACL___foo__SWIG_0" :type :function :arity 2) ((PARM0_f1 cl:single-float :float ) (PARM1_f2 cl:single-float :float )) (:returning (:int ) :call-direct t :strings-convert nil) (let ((SWIG_arg0 PARM0_f1)) (let ((SWIG_arg1 PARM1_f2)) (swig-ff-call SWIG_arg0 SWIG_arg1)))) (swig-defmethod ("foo" "ACL___foo__SWIG_1" :type :function :arity 2) ((PARM0_f1 cl:single-float :float ) (PARM1_c2 cl:character :char character)) (:returning (:int ) :call-direct t :strings-convert nil) (let ((SWIG_arg0 PARM0_f1)) (let ((SWIG_arg1 PARM1_c2)) (swig-ff-call SWIG_arg0 SWIG_arg1)))) (swig-dispatcher ("foo" :type :function :arities (2))) (swig-defun ("bar" "ACL___bar__SWIG_0" :type :function) ((PARM0_lisp_fn (* :void) )) (:returning (:void ) :release-heap :never :optimize-for-space t :strings-convert nil) (let ((SWIG_arg0 PARM0_lisp_fn)) (swig-ff-call SWIG_arg0))) (swig-defun ("xxx" "ACL___xxx__SWIG_0" :type :function) (:void) (:returning ((* :char) ) :strings-convert t) (swig-ff-call)) %ffargs(strings_convert="t");
Is the only default value specified in 17.2.4 Non-overloaded Defuns
These are simple defuns. There is no typechecking of arguments. Parameters are bound to local variables for possible transformation of values, such as pulling values out of instance slots or allocating temporary stack allocated structures, via the 17.2.5 Overloaded Defuns
In the case of overloaded functions, mulitple layers are generated. First, all the overloads for a given name are separated out into groups based on arity, and are wrapped in defmethods. Each method calls a distinct wrapper function, but are themselves distinguished by the types of their arguments (see 17.2.6 What about constant and variable access?
Along with the described functional layering, when creating a .cxx wrapper, this module will generate getter and–if not immutable–setter, functions for variables and constants. If the -nocwrap option is used, 17.2.7 Object WrappingAll non-primitive types (Classes, structs, unions, and typedefs involving same) have a corresponding foreign-type defined on the lisp side via ff:def-foreign-type. All non-primitive types are further represented by a CLOS class, created via defclass. An attempt is made to create the same class hierarchy, with all classes inheriting directly or indirectly from ff:foreign-pointer. Further, wherever it is apparent, all pointers returned from foreign code are wrapped in a CLOS instance of the appropriate class. For ff:def-foreign-calls that have been defined to expect a :foreign-address type as argument, these CLOS instances can legally be passed and the pointer to the C++ object automatically extracted. This is a natural feature of Allegro's foreign function interface. 17.3 Wrapping DetailsIn this section is described how particular C/C++ constructs are translated into lisp. 17.3.1 Namespaces
C++ namespaces are translated into Lisp packages by SWIG. The Global namespace is mapped to a package named by the foo.i: %module foo %{ #include "foo.h" %} %include "foo.h" namespace car { ... namespace tires { int do_something(int n); } } Generates the following code. foo.cl (defpackage :foo (:use :common-lisp :swig :ff :excl)) ... (swig-defpackage ("car")) (swig-defpackage ("car" "tires")) ... (swig-in-package ("car" "tires")) (swig-defun ("do_something" "ACL_car_tires__do_something__SWIG_0" :type :function) ((PARM0_n :int )) (:returning (:int ) :strings-convert t) (let ((SWIG_arg0 PARM0_n)) (swig-ff-call SWIG_arg0))) The above interface file would cause packages foo, foo.car, and foo.car.tires to be created. One would find the function wrapper for do_something defined in the foo.car.tires package(*).
(*) Except for the package named by the module, all namespace names are passed to the identifier-converter-function as strings with a
Note that packages created by 17.3.2 Constants
Constants, as declared by the preprocessor #define macro or SWIG Here are examples of simple preprocessor constants when using -nocwrap. #define A 1 => (swig-defconstant "A" 1) #define B 'c' => (swig-defconstant "B" #\c) #define C B => (swig-defconstant "C" #\c) #define D 1.0e2 => (swig-defconstant "D" 1.0d2) #define E 2222 => (swig-defconstant "E" 2222) #define F (unsigned int)2222 => no code generated #define G 1.02e2f => (swig-defconstant "G" 1.02f2) #define H foo => no code generated Note that where SWIG is unable to determine if a constant is a literal, no node is added to the SWIG parse tree, and so no values can be generated. For preprocessor constants containing expressions which can be reduced to literal values, nodes are created, but with no simplification of the constant value. A very very simple infix to prefix converter has been implemented that tries to do the right thing for simple cases, but does not for more complex expressions. If the literal parser determines that something is wrong, a warning will be generated and the literal expression will be included in the generated code, but commented out. #define I A + E => (swig-defconstant "I" (+ 1 2222)) #define J 1|2 => (swig-defconstant "J" (logior 1 2)) #define Y 1 + 2 * 3 + 4 => (swig-defconstant "Y" (* (+ 1 2) (+ 3 4))) #define Y1 (1 + 2) * (3 + 4) => (swig-defconstant "Y1" (* (+ 1 2) (+ 3 4))) #define Y2 1 * 2 + 3 * 4 => (swig-defconstant "Y2" (* 1 (+ 2 3) 4)) ;; WRONG #define Y3 (1 * 2) + (3 * 4) => (swig-defconstant "Y3" (* 1 (+ 2 3) 4)) ;; WRONG #define Z 1 + 2 - 3 + 4 * 5 => (swig-defconstant "Z" (* (+ 1 (- 2 3) 4) 5)) ;; WRONG
Users are cautioned to get to know their constants before use, or not use the 17.3.3 VariablesFor C wrapping, a def-foreign-variable call is generated for access to global variables. When wrapping C++ code, both global and member variables, getter wrappers are generated for accessing their value, and if not immutable, setter wrappers as well. In the example below, note the lack of a setter wrapper for global_var, defined as const. vars.h namespace nnn { int const global_var = 2; float glob_float = 2.0; } Generated code: vars.cl (swig-in-package ("nnn")) (swig-defun ("global_var" "ACL_nnn__global_var_get__SWIG_0" :type :getter) (:void) (:returning (:int ) :strings-convert t) (swig-ff-call)) (swig-defun ("glob_float" "ACL_nnn__glob_float_set__SWIG_0" :type :setter) ((PARM0_glob_float :float )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 PARM0_glob_float)) (swig-ff-call SWIG_arg0))) (swig-defun ("glob_float" "ACL_nnn__glob_float_get__SWIG_0" :type :getter) (:void) (:returning (:float ) :strings-convert t) (swig-ff-call)) Note also, that where applicable, setter wrappers are implemented as setf methods on the getter function, providing a lispy interface to the foreign code. user> (load "globalvar.dll") ; Foreign loading globalvar.dll. t user> (load "globalvar.cl") ; Loading c:\mikel\src\swig\test\globalvar.cl t user> globalvar> (globalvar.nnn::global_var) 2 globalvar> (globalvar.nnn::glob_float) 2.0 globalvar> (setf (globalvar.nnn::glob_float) 3.0) 3.0 globalvar> (globalvar.nnn::glob_float) 3.0 17.3.4 Enumerations
In C, an enumeration value is an integer value, while in C++ an enumeration value is implicitly convertible to an integer value, but can also be distinguished by it's enum type. For each enum declaration a def-foreign-type is generated, assigning the enum a default type of :int. Users may adjust the foreign type of enums via SWIG Enum values are a bit trickier as they can be initialized using any valid C/C++ expression. In C with the -nocwrap command-line option, we handle the typical cases (simple integer initialization) and generate a defconstant form for each enum value. This has the advantage of it not being necessary to probe into foreign space to retrieve enum values. When generating a .cxx wrapper file, a more general solution is employed. A wrapper variable is created in the module_wrap.cxx file, and a ff:def-foreign-variable call is generated to retrieve it's value into lisp. For example, the following header file enum.h: enum COL { RED, GREEN, BLUE }; enum FOO { FOO1 = 10, FOO2, FOO3 }; In -nocwrap mode, generates enum.cl: (swig-def-foreign-type "COL" :int) (swig-defconstant "RED" 0) (swig-defconstant "GREEN" (+ #.(swig-insert-id "RED" () :type :constant) 1)) (swig-defconstant "BLUE" (+ #.(swig-insert-id "GREEN" () :type :constant) 1)) (swig-def-foreign-type "FOO" :int) (swig-defconstant "FOO1" 10) (swig-defconstant "FOO2" (+ #.(swig-insert-id "FOO1" () :type :constant) 1)) (swig-defconstant "FOO3" (+ #.(swig-insert-id "FOO2" () :type :constant) 1)) And when generating a .cxx wrapper enum_wrap.cxx: EXPORT const int ACL_ENUM___RED__SWIG_0 = RED; EXPORT const int ACL_ENUM___GREEN__SWIG_0 = GREEN; EXPORT const int ACL_ENUM___BLUE__SWIG_0 = BLUE; EXPORT const int ACL_ENUM___FOO1__SWIG_0 = FOO1; EXPORT const int ACL_ENUM___FOO2__SWIG_0 = FOO2; EXPORT const int ACL_ENUM___FOO3__SWIG_0 = FOO3; and enum.cl: (swig-def-foreign-type "COL" :int) (swig-defvar "RED" "ACL_ENUM___RED__SWIG_0" :type :constant) (swig-defvar "GREEN" "ACL_ENUM___GREEN__SWIG_0" :type :constant) (swig-defvar "BLUE" "ACL_ENUM___BLUE__SWIG_0" :type :constant) (swig-def-foreign-type "FOO" :int) (swig-defvar "FOO1" "ACL_ENUM___FOO1__SWIG_0" :type :constant) (swig-defvar "FOO2" "ACL_ENUM___FOO2__SWIG_0" :type :constant) (swig-defvar "FOO3" "ACL_ENUM___FOO3__SWIG_0" :type :constant) 17.3.5 ArraysOne limitation in the Allegro CL foreign-types module, is that, without macrology, expressions may not be used to specify the dimensions of an array declaration. This is not a horrible drawback unless it is necessary to allocate foreign structures based on the array declaration using ff:allocate-fobject. When it can be determined that an array bound is a valid numeric value, SWIG will include this in the generated array declaration on the lisp side, otherwise the value will be included, but commented out. Below is a comprehensive example, showing a number of legal C/C++ array declarations and how they are translated into foreign-type specifications in the generated lisp code. array.h #define MAX_BUF_SIZE 1024 namespace FOO { int global_var1[13]; float global_var2[MAX_BUF_SIZE]; } enum COLOR { RED = 10, GREEN = 20, BLUE, PURPLE = 50, CYAN }; namespace BAR { char global_var3[MAX_BUF_SIZE + 1]; float global_var4[MAX_BUF_SIZE][13]; signed short global_var5[MAX_BUF_SIZE + MAX_BUF_SIZE]; int enum_var5[GREEN]; int enum_var6[CYAN]; COLOR enum_var7[CYAN][MAX_BUF_SIZE]; } Generates: array.cl (in-package #.*swig-module-name*) (swig-defpackage ("FOO")) (swig-defpackage ("BAR")) (swig-in-package ()) (swig-def-foreign-type "COLOR" :int) (swig-defvar "RED" "ACL_ENUM___RED__SWIG_0" :type :constant) (swig-defvar "GREEN" "ACL_ENUM___GREEN__SWIG_0" :type :constant) (swig-defvar "BLUE" "ACL_ENUM___BLUE__SWIG_0" :type :constant) (swig-defvar "PURPLE" "ACL_ENUM___PURPLE__SWIG_0" :type :constant) (swig-defvar "CYAN" "ACL_ENUM___CYAN__SWIG_0" :type :constant) (swig-in-package ()) (swig-defconstant "MAX_BUF_SIZE" 1024) (swig-in-package ("FOO")) (swig-defun ("global_var1" "ACL_FOO__global_var1_get__SWIG_0" :type :getter) (:void) (:returning ((* :int) ) :strings-convert t) (make-instance 'ff:foreign-pointer :foreign-address (swig-ff-call))) (swig-defun ("global_var2" "ACL_FOO__global_var2_set__SWIG_0" :type :setter) ((global_var2 (:array :float 1024) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 global_var2)) (swig-ff-call SWIG_arg0))) (swig-in-package ()) (swig-in-package ("BAR")) (swig-defun ("global_var3" "ACL_BAR__global_var3_set__SWIG_0" :type :setter) ((global_var3 (:array :char #|1024+1|#) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 global_var3)) (swig-ff-call SWIG_arg0))) (swig-defun ("global_var4" "ACL_BAR__global_var4_set__SWIG_0" :type :setter) ((global_var4 (:array (:array :float 13) 1024) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 global_var4)) (swig-ff-call SWIG_arg0))) (swig-defun ("global_var4" "ACL_BAR__global_var4_get__SWIG_0" :type :getter) (:void) (:returning ((* (:array :float 13)) ) :strings-convert t) (make-instance 'ff:foreign-pointer :foreign-address (swig-ff-call))) (swig-defun ("global_var5" "ACL_BAR__global_var5_set__SWIG_0" :type :setter) ((global_var5 (:array :short #|1024+1024|#) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 global_var5)) (swig-ff-call SWIG_arg0))) (swig-defun ("enum_var5" "ACL_BAR__enum_var5_set__SWIG_0" :type :setter) ((enum_var5 (:array :int #|GREEN|#) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 enum_var5)) (swig-ff-call SWIG_arg0))) (swig-defun ("enum_var6" "ACL_BAR__enum_var6_set__SWIG_0" :type :setter) ((enum_var6 (:array :int #|CYAN|#) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 enum_var6)) (swig-ff-call SWIG_arg0))) (swig-defun ("enum_var7" "ACL_BAR__enum_var7_set__SWIG_0" :type :setter) ((enum_var7 (:array (:array #.(swig-insert-id "COLOR" ()) 1024) #|CYAN|#) )) (:returning (:void ) :strings-convert t) (let ((SWIG_arg0 enum_var7)) (swig-ff-call SWIG_arg0))) (swig-defun ("enum_var7" "ACL_BAR__enum_var7_get__SWIG_0" :type :getter) (:void) (:returning ((* (:array #.(swig-insert-id "COLOR" ()) 1024)) ) :strings-convert t) (make-instance 'ff:foreign-pointer :foreign-address (swig-ff-call))) 17.3.6 Classes and Structs and Unions (oh my!)17.3.6.1 CLOS wrapping of
Classes, unions, and structs are all treated the same way by the interface generator. For any of these objects, a def-foreign-type and a defclass form are generated. For every function that returns an object (or pointer/reference) of C/C++ type 17.3.6.2 CLOS InheritanceThe CLOS class schema generated by the interface mirrors the inheritance of the classes in foreign code, with the ff:foreign-pointer class at its root. ff:foreign-pointer is a thin wrapper for pointers that is made available by the foreign function interface. It's key benefit is that it may be passed as an argument to any ff:def-foreign-call that is expecting a pointer as the parameter. 17.3.6.3 Member fields and functionsAll public fields will have accessor getter/setter functions generated for them, as appropriate. All public member functions will have wrapper functions generated.
We currently ignore anything that isn't 17.3.6.4 Why not directly access C++ classes using foreign types?The def-foreign-type generated by the SWIG interface is currently incomplete. We can reliably generate the object layout of simple structs and unions; they can be allocated via ff:allocate-fobject, and their member variables accessed directly using the various ff:fslot-value-* functions. However, the layout of C++ classes is more complicated. Different compilers adjust class layout based on inheritance patterns, and the presence of virtual member functions. The size of member function pointers vary across compilers as well. As a result, it is recommended that users of any generated interface not attempt to access C++ instances via the foreign type system, but instead use the more robust wrapper functions. 17.3.7 Templates17.3.7.1 Generating wrapper code for templates
SWIG provides support for dealing with templates, but by default, it will not generate any member variable or function wrappers for templated classes. In order to create these wrappers, you need to explicitly tell SWIG to instantiate them. This is done via the 17.3.7.2 Implicit Template instantiationWhile no wrapper code is generated for accessing member variables, or calling member functions, type code is generated to include these templated classes in the foreign-type and CLOS class schema. 17.3.8 Typedef, Templates, and Synonym Types
In C/C++ it is possible, via typedef, to have many names refer to the same synonyms.h class A { int x; int y; }; typedef A Foo; A *xxx(int i); /* sets A->x = A->y = i */ Foo *yyy(int i); /* sets Foo->x = Foo->y = i */ int zzz(A *inst = 0); /* return inst->x + inst->y */
The function We resolve this issue, by noting synonym relationships between types while generating the interface. A Primary type is selected (more on this below) from the candidate list of synonyms. For all other synonyms, intead of generating a distinct CLOS class definition, we generate a form that expands to:
The result is that all references to synonym types in foreign code, are wrapped in the same CLOS wrapper, and, in particular, method specialization in wrapping generic functions works as expected. Given the above header file, synonym.h, a Lisp session would appear as follows: CL-USER> (load "synonym.dll") ; Foreign loading synonym.dll. t CL-USER> (load "synonym.cl") ; Loading c:\mikel\src\swig\test\synonym.cl t CL-USER> synonym> (setf a (xxx 3)) #<A nil #x3261a0 @ #x207299da> synonym> (setf foo (yyy 10)) #<A nil #x3291d0 @ #x2072e982> synonym> (zzz a) 6 synonym> (zzz foo) 20 synonym> 17.3.8.1 Choosing a primary typeThe choice of a primary type is selected by the following criteria from a set of synonym types.
17.3.9 Function overloading/Parameter defaultingFor each possible argument combination, a distinct wrapper function is created in the .cxx file. On the Lisp side, a generic functions is defined for each possible arity the overloaded/defaulted call may have. Each distinct wrapper is then called from within a defmethod on the appropriate generic function. These are further wrapped inside a dispatch function that checks the number of arguments it is called with and passes them via apply to the appropriate generic-function. This allows for a single entry point to overloaded functions on the lisp side. Example: overload.h: class A { public: int x; int y; }; float xxx(int i, int x = 0); /* return i * x */ float xxx(A *inst, int x); /* return x + A->x + A->y */ Creates the following three wrappers, for each of the possible argument combinations overload_wrap.cxx EXPORT void ACL___delete_A__SWIG_0 (A *larg1) { A *arg1 = (A *) 0 ; arg1 = larg1; try { delete arg1; } catch (...) { } } EXPORT float ACL___xxx__SWIG_0 (int larg1, int larg2) { float lresult = (float)0 ; int arg1 ; int arg2 ; float result; arg1 = larg1; arg2 = larg2; try { result = (float)xxx(arg1,arg2); lresult = result; return lresult; } catch (...) { return (float)0; } } EXPORT float ACL___xxx__SWIG_1 (int larg1) { float lresult = (float)0 ; int arg1 ; float result; arg1 = larg1; try { result = (float)xxx(arg1); lresult = result; return lresult; } catch (...) { return (float)0; } } EXPORT float ACL___xxx__SWIG_2 (A *larg1, int larg2) { float lresult = (float)0 ; A *arg1 = (A *) 0 ; int arg2 ; float result; arg1 = larg1; arg2 = larg2; try { result = (float)xxx(arg1,arg2); lresult = result; return lresult; } catch (...) { return (float)0; } } And the following foreign-function-call and method definitions on the lisp side: overload.cl (swig-defmethod ("xxx" "ACL___xxx__SWIG_0" :type :function :arity 2) ((PARM0_i cl:integer :int ) (PARM1_x cl:integer :int )) (:returning (:float ) :strings-convert t) (let ((SWIG_arg0 PARM0_i)) (let ((SWIG_arg1 PARM1_x)) (swig-ff-call SWIG_arg0 SWIG_arg1)))) (swig-defmethod ("xxx" "ACL___xxx__SWIG_1" :type :function :arity 1) ((PARM0_i cl:integer :int )) (:returning (:float ) :strings-convert t) (let ((SWIG_arg0 PARM0_i)) (swig-ff-call SWIG_arg0))) (swig-defmethod ("xxx" "ACL___xxx__SWIG_2" :type :function :arity 2) ((PARM0_inst #.(swig-insert-id "A" () :type :class) (* #.(swig-insert-id "A" ())) ) (PARM1_x cl:integer :int )) (:returning (:float ) :strings-convert t) (let ((SWIG_arg0 PARM0_inst)) (let ((SWIG_arg1 PARM1_x)) (swig-ff-call SWIG_arg0 SWIG_arg1)))) (swig-dispatcher ("xxx" :type :function :arities (1 2))) And their usage in a sample lisp session: overload> (setf a (new_A)) #<A nil #x329268 @ #x206cf612> overload> (setf (A_x a) 10) 10 overload> (setf (A_y a) 20) 20 overload> (xxx 1) 0.0 overload> (xxx 3 10) 30.0 overload> (xxx a 1) 31.0 overload> (xxx a 2) 32.0 overload> 17.3.10 Operator wrapping and Operator overloading
Wrappers to defined C++ Operators are automatically renamed, using /* name conversion for overloaded operators. */ #ifdef __cplusplus %rename(__add__) *::operator+; %rename(__pos__) *::operator+(); %rename(__pos__) *::operator+() const; %rename(__sub__) *::operator-; %rename(__neg__) *::operator-() const; %rename(__neg__) *::operator-(); %rename(__mul__) *::operator*; %rename(__deref__) *::operator*(); %rename(__deref__) *::operator*() const; %rename(__div__) *::operator/; %rename(__mod__) *::operator%; %rename(__logxor__) *::operator^; %rename(__logand__) *::operator&; %rename(__logior__) *::operator|; %rename(__lognot__) *::operator~(); %rename(__lognot__) *::operator~() const; %rename(__not__) *::operator!(); %rename(__not__) *::operator!() const; %rename(__assign__) *::operator=; %rename(__add_assign__) *::operator+=; %rename(__sub_assign__) *::operator-=; %rename(__mul_assign__) *::operator*=; %rename(__div_assign__) *::operator/=; %rename(__mod_assign__) *::operator%=; %rename(__logxor_assign__) *::operator^=; %rename(__logand_assign__) *::operator&=; %rename(__logior_assign__) *::operator|=; %rename(__lshift__) *::operator<<; %rename(__lshift_assign__) *::operator<<=; %rename(__rshift__) *::operator>>; %rename(__rshift_assign__) *::operator>>=; %rename(__eq__) *::operator==; %rename(__ne__) *::operator!=; %rename(__lt__) *::operator<; %rename(__gt__) *::operator>; %rename(__lte__) *::operator<=; %rename(__gte__) *::operator>=; %rename(__and__) *::operator&&; %rename(__or__) *::operator||; %rename(__preincr__) *::operator++(); %rename(__postincr__) *::operator++(int); %rename(__predecr__) *::operator--(); %rename(__postdecr__) *::operator--(int); %rename(__comma__) *::operator,(); %rename(__comma__) *::operator,() const; %rename(__member_ref__) *::operator->; %rename(__member_func_ref__) *::operator->*; %rename(__funcall__) *::operator(); %rename(__aref__) *::operator[];
Name mangling occurs on all such renamed identifiers, so that wrapper name generated by
Operator overloading can be achieved by adding functions based on the mangled names of the function. In the following example, a class B is defined with a Operator== method defined. The swig opoverload.h class B { public: int x; int y; bool operator==(B const& other) const; }; and opoverload.i %module opoverload %{ #include <fstream> #include "opoverload.h" %} %{ bool B___eq__(B const *inst, int const x) { // insert the function definition into the wrapper code before // the wrapper for it. // ... do stuff ... } %} %include "opoverload.h" %extend B { public: bool __eq__(int const x) const; }; Either operator can be called via a single call to the dispatch function: opoverload> (B___eq__ x1 x2) nil opoverload> (B___eq__ x1 3) nil opoverload> 17.3.11 Varargs
Variable length argument lists are not supported, by default. If such a function is encountered, a warning will generated to stderr. Varargs are supported via the SWIG
See the following section on Variable Length arguments provides examples on how 17.3.12 C++ ExceptionsEach C++ wrapper includes a handler to catch any exceptions that may be thrown while in foreign code. This helps prevent simple C++ errors from killing the entire lisp process. There is currently no mechanism to have these exceptions forwarded to the lisp condition system, nor has any explicit support of the exception related SWIG typemaps been implemented. 17.3.13 Pass by value, pass by reference
Allegro CL does not support the passing of non-primitive foreign structures by value. As a result, SWIG must automatically detect and convert function parameters and return values to pointers whenever necessary. This is done via the use of 17.4 TypemapsSWIG Typemaps provide a powerful tool for automatically generating code to handle various menial tasks required of writing an interface to foreign code. The purpose of this section is to describe each of the typemaps used by the Allegro CL module. Please read the chapter on Typemaps for more information. 17.4.1 Code Generation in the C++ WrapperEvery C++ wrapper generated by SWIG takes the following form: return-val wrapper-name(parm0, parm1, ..., parmN) { return-val lresult; /* return value from wrapper */ <local-declaration> ... results; /* return value from function call */ <binding locals to parameters> try { result = function-name(local0, local1, ..., localN); <convert and bind result to lresult> return lresult; catch (...) { return (int)0; } 17.4.1.1 IN Typemap
the
These are the default specifications for the IN typemap. Here, %typemap(in) bool "$1 = (bool)$input;"; %typemap(in) char, unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, float, double, long double, char *, void *, void, enum SWIGTYPE, SWIGTYPE *, SWIGTYPE[ANY], SWIGTYPE & "$1 = $input;"; %typemap(in) SWIGTYPE "$1 = *$input;"; 17.4.1.2 OUT Typemap
The %typemap(out) bool "$result = (int)$1;"; %typemap(out) char, unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, float, double, long double, char *, void *, void, enum SWIGTYPE, SWIGTYPE *, SWIGTYPE[ANY], SWIGTYPE & "$result = $1;"; %typemap(out) SWIGTYPE "$result = new $1_type($1);"; 17.4.1.3 CTYPE TypemapThis typemap is not used for code generation, but purely for the transformation of types in the parameter list of the wrapper function. It's primary use is to handle by-value to by-reference conversion in the wrappers parameter list. Its default settings are: %typemap(ctype) bool "int"; %typemap(ctype) char, unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, float, double, long double, char *, void *, void, enum SWIGTYPE, SWIGTYPE *, SWIGTYPE[ANY], SWIGTYPE & "$1_ltype"; %typemap(ctype) SWIGTYPE "$&1_type"; These three typemaps are specifically employed by the the Allegro CL interface generator. SWIG also implements a number of other typemaps that can be used for generating code in the C/C++ wrappers. You can read about these common typemaps here. 17.4.2 Code generation in Lisp wrappersA number of custom typemaps have also been added to facilitate the generation of code in the lisp side of the interface. These are described below. The basic code generation structure is applied as a series of nested expressions, one for each parameter, then one for manipulating the return value, and last, the foreign function call itself. Note that the typemaps below use fully qualified symbols where necessary. Users writing their own typemaps should do likewise. See the explanation in the last paragraph of 16.3.1 Namespaces for details. 17.4.2.1 LIN TypemapThe LIN typemap allows for the manipulating the lisp objects passed as arguments to the wrapping defun before passing them to the foreign function call. For example, when passing lisp strings to foreign code, it is often necessary to copy the string into a foreign structure of type (:char *) of appropriate size, and pass this copy to the foreign call. Using the LIN typemap, one could arrange for the stack-allocation of a foreign char array, copy your string into it, and not have to worry about freeing the copy after the function returns.
The LIN typemap accepts the following
%typemap(lin) SWIGTYPE "(cl:let (($out $in))\n $body)"; 17.4.2.2 LOUT TypemapThe LOUT typemap is the means by which we effect the wrapping of foreign pointers in CLOS instances. It is applied after all LIN typemaps, and immediately before the actual foreign-call. The LOUT typemap uses the following $variable
%typemap(lout) bool, char, unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, float, double, long double, char *, void *, void, enum SWIGTYPE "$body"; %typemap(lout) SWIGTYPE[ANY], SWIGTYPE *, SWIGTYPE & "(cl:make-instance '$lclass :foreign-address $body)"; %typemap(lout) SWIGTYPE "(cl:let* ((address $body)\n (ACL_result (cl:make-instance '$lclass :foreign-address address)))\n (cl:unless (cl::zerop address)\n (excl:schedule-finalization ACL_result #'$ldestructor))\n ACL_result)"; 17.4.2.3 FFITYPE TypemapThe FFITYPE typemap works as a helper for a body of code that converts C/C++ type specifications into Allegro CL foreign-type specifications. These foreign-type specifications appear in ff:def-foreing-type declarations, and in the argument list and return values of ff:def-foreign-calls. You would modify this typemap if you want to change how the FFI passes through arguments of a given type. For example, if you know that a particular compiler represents booleans as a single byte, you might add an entry for: %typemap(ffitype) bool ":unsigned-char"; Note that this typemap is pure type transformation, and is not used in any code generations step the way the LIN and LOUT typemaps are. The default mappings for this typemap are: %typemap(ffitype) bool ":int"; %typemap(ffitype) char ":char"; %typemap(ffitype) unsigned char ":unsigned-char"; %typemap(ffitype) signed char ":char"; %typemap(ffitype) short, signed short ":short"; %typemap(ffitype) unsigned short ":unsigned-short"; %typemap(ffitype) int, signed int ":int"; %typemap(ffitype) unsigned int ":unsigned-int"; %typemap(ffitype) long, signed long ":long"; %typemap(ffitype) unsigned long ":unsigned-long"; %typemap(ffitype) float ":float"; %typemap(ffitype) double ":double"; %typemap(ffitype) char * "(* :char)"; %typemap(ffitype) void * "(* :void)"; %typemap(ffitype) void ":void"; %typemap(ffitype) enum SWIGTYPE ":int"; %typemap(ffitype) SWIGTYPE & "(* :void)"; 17.4.2.4 LISPTYPE TypemapThis is another type only transformation map, and is used to provide the lisp-type, which is the optional third argument in argument specifier in a ff:def-foreign-call form. Specifying a lisp-type allows the foreign call to perform type checking on the arguments passed in. The default entries in this typemap are: %typemap(lisptype) bool "cl:boolean"; %typemap(lisptype) char "cl:character"; %typemap(lisptype) unsigned char "cl:integer"; %typemap(lisptype) signed char "cl:integer"; 17.4.2.5 LISPCLASS TypemapThe LISPCLASS typemap is used to generate the method signatures for the generic-functions which wrap overloaded functions and functions with defaulted arguments. The default entries are: %typemap(lispclass) bool "t"; %typemap(lispclass) char "cl:character"; %typemap(lispclass) unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, enum SWIGTYPE "cl:integer"; %typemap(lispclass) float "cl:single-float"; %typemap(lispclass) double "cl:double-float"; %typemap(lispclass) char * "cl:string"; 17.4.3 Modifying SWIG behavior using typemapsThe following example shows how we made use of the above typemaps to add support for the wchar_t type. %typecheck(SWIG_TYPECHECK_UNICHAR) wchar_t { $1 = 1; }; %typemap(in) wchar_t "$1 = $input;"; %typemap(lin) wchar_t "(cl:let (($out (cl:char-code $in)))\n $body)"; %typemap(lin) wchar_t* "(excl:with-native-string ($out $in :external-format #+little-endian :fat-le #-little-endian :fat)\n $body)" %typemap(out) wchar_t "$result = $1;"; %typemap(lout) wchar_t "(cl:code-char $body)"; %typemap(lout) wchar_t* "(excl:native-to-string $body :external-format #+little-endian :fat-le #-little-endian :fat)"; %typemap(ffitype) wchar_t ":unsigned-short"; %typemap(lisptype) wchar_t ""; %typemap(ctype) wchar_t "wchar_t"; %typemap(lispclass) wchar_t "cl:character"; %typemap(lispclass) wchar_t* "cl:string"; 17.5 Identifier Converter functions17.5.1 Creating symbols in the lisp environmentVarious symbols must be generated in the lisp environment to which class definitions, functions, constants, variables, etc. must be bound. Rather than force a particular convention for naming these symbols, an identifier (to symbol) conversion function is used. A user-defined identifier-converter can then implement any symbol naming, case-modifying, scheme desired. In generated SWIG code, whenever some interface object must be referenced by its lisp symbol, a macro is inserted that calls the identifier-converter function to generate the appropriate symbol reference. It is therefore expected that the identifier-converter function reliably return the same (eq) symbol given the same set of arguments. 17.5.2 Existing identifier-converter functionsTwo basic identifier routines have been defined. 17.5.2.1 identifier-convert-nullNo modification of the identifier string is performed. Based on other arguments, the identifier may be concatenated with other strings, from which a symbol will be created. 17.5.2.2 identifier-convert-lispifyAll underscores in the identifier string are converted to hyphens. Otherwise, identifier-convert-lispify performs the same symbol transformations. 17.5.2.3 Default identifier to symbol conversions
Check the definitions of the above two default identifier-converters in 17.5.3 Defining your own identifier-converterA user-defined identifier-converter function should conform to the following specification: (defun identifier-convert-fn (id &key type class arity) ...body...) result ==> symbol or (setf symbol)
The The :type keyword argument provides more information on the type of identifier. It's value is a symbol. This allows the identifier-converter to apply different heuristics when mapping different types of identifiers to symbols. SWIG will generate calls to your identifier-converter using the following types.
The :class keyword argument is a string naming a foreign class. When non-nil, it indicates that the current identifier has scope in the specified class. The :arity keyword argument only appears in swig:swig-defmethod forms generated for overloaded functions. It's value is an integer indicating the number of arguments passed to the routine indicated by this identifier. 17.5.4 Instructing SWIG to use a particular identifier-converter
By default, SWIG will use identifier-converter-null. To specify another convert function, use the % swig -allegrocl -c++ -module mymodule -identifier-converter my-identifier-converter 18 SWIG and C#18.1 IntroductionThe purpose of the C# module is to offer an automated way of accessing existing C/C++ code from .NET languages. The wrapper code implementation uses C# and the Platform Invoke (PInvoke) interface to access natively compiled C/C++ code. The PInvoke interface has been chosen over Microsoft's Managed C++ interface as it is portable to both Microsoft Windows and non-Microsoft platforms. PInvoke is part of the ECMA/ISO C# specification. It is also better suited for robust production environments due to the Managed C++ flaw called the Mixed DLL Loading Problem. Swig C# works equally well on non-Microsoft operating systems such as Linux, Solaris and Apple Mac using Mono and Portable.NET. To get the most out of this chapter an understanding of interop is required. The Microsoft Developer Network (MSDN) has a good reference guide in a section titled “Interop Marshaling”. Monodoc, available from the Mono project, has a very useful section titled Interop with native libraries. 18.2 Differences to the Java moduleThe C# module is very similar to the Java module, so until some more complete documentation has been written, please use the Java documentation as a guide to using SWIG with C#. The C# module has the same major SWIG features as the Java module. The rest of this section should be read in conjunction with the Java documentation as it lists the main differences. The most notable differences to Java are the following:
… } Note that by default, the generated C# classes have no namespace and the module name is unrelated to namespaces. The module name is just like in Java and is merely used to name some of the generated classes.
jni → ctype jtype → imtype jstype → cstype javain → csin javaout → csout javadirectorin → csdirectorin javadirectorout → csdirectorout javainterfaces → csinterfaces and csinterfaces_derived javabase → csbase javaclassmodifiers → csclassmodifiers javacode → cscode javaimports → csimports javabody → csbody javafinalize → csfinalize javadestruct → csdestruct javadestruct_derived → csdestruct_derived
csvarout C# code property get typemap csattributes C# attributes for attaching to proxy classes/enums
%javaconstvalue → %csconstvalue %javamethodmodifiers → %csmethodmodifiers
jniclassbase → imclassbase jniclassclassmodifiers → imclassclassmodifiers jniclasscode → imclasscode jniclassimports → imclassimports jniclassinterfaces → imclassinterfaces
$&javaclassname → $&csclassname $*javaclassname → $*csclassname $javainput → $csinput $jnicall → $imcall
char * function(char *); The output type is thus IntPtr and the input type is string. The resulting intermediary C# code is: public static extern IntPtr function(string jarg1);
inattributes=“[MarshalAs(UnmanagedType.LPStr)]”, outattributes="[return: MarshalAs(UnmanagedType.LPStr)]") const char * "String" const char * GetMsg() {} void SetMsg(const char *msg) {} The intermediary class will then have the marshalling as specified by everything in the 'imtype' typemap: class examplePINVOKE { ... [DllImport("example", EntryPoint="CSharp_GetMsg")] [return: MarshalAs(UnmanagedType.LPStr)] public static extern String GetMsg(); [DllImport("example", EntryPoint="CSharp_SetMsg")] public static extern void SetMsg%%([%%MarshalAs(UnmanagedType.LPStr)]String jarg1);
}
Note that the
%csattributes AClass::AClass(double d) “[ThreadSafe(false)]” %csattributes AClass::AMethod() “[ThreadSafe(true)]” %inline %{ class AClass { public: AClass(double a) {} void AMethod() {} }; %} will generate a C# proxy class: [ThreadSafe] public class AClass : IDisposable { ... [ThreadSafe(false)] public AClass(double a) ... [ThreadSafe(true)] public void AMethod() ...
}
If C# attributes need adding to the
If
The directory 18.3 C# Arrays
There are various ways to pass arrays from C# to C/C++. The default wrapping treats arrays as pointers and as such simple type wrapper classes are generated, eg 18.3.1 The SWIG C arrays libraryThe C arrays library keeps all the array memory in the unmanaged layer. The library is available to all language modules and is documented in the carrays.i library section. Please refer to this section for details, but for convenience, the C# usage for the two examples outlined there is shown below.
For the SWIGTYPE_p_double a = example.new_doubleArray(10); // Create an array for (int i=0; i<10; i++) example.doubleArray_setitem(a,i,2*i); // Set a value example.print_array(a); // Pass to C example.delete_doubleArray(a); // Destroy array
and for the doubleArray c = new doubleArray(10); // Create double[10] for (int i=0; i<10; i++) c.setitem(i, 2*i); // Assign values example.print_array(c.cast()); // Pass to C 18.3.2 Managed arrays using P/Invoke default array marshallingIn the P/Invoke default marshalling scheme, one needs to designate whether the invoked function will treat a managed array parameter as input, output, or both. When the function is invoked, the CLR allocates a separate chunk of memory as big as the given managed array, which is automatically released at the end of the function call. If the array parameter is marked as being input, the content of the managed array is copied into this buffer when the call is made. Correspondingly, if the array parameter is marked as being output, the contents of the reserved buffer are copied back into the managed array after the call returns. A pointer to to this buffer is passed to the native function. The reason for allocating a separate buffer is to leave the CLR free to relocate the managed array object during garbage collection. If the overhead caused by the copying is causing a significant performance penalty, consider pinning the managed array and passing a direct reference as described in the next section. For more information on the subject, see the Default Marshaling for Arrays article on MSDN.
The P/Invoke default marshalling is supported by the void myArrayCopy(int *sourceArray, int *targetArray, int nitems); We can now instruct SWIG to use the default marshalling typemaps by %include "arrays_csharp.i" %apply int INPUT[] {int *sourceArray} %apply int OUTPUT[] {int *targetArray} As a result, we get the following method in the module class: public static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) { examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems); } If we look beneath the surface at the corresponding intermediary class code, we see that SWIG has generated code that uses attributes (from the System.Runtime.InteropServices namespace) to tell the CLR to use default marshalling for the arrays: [DllImport("example", EntryPoint="CSharp_myArrayCopy")] public static extern void myArrayCopy([In, MarshalAs(UnmanagedType.LPArray)]int[] jarg1, [Out, MarshalAs(UnmanagedType.LPArray)]int[] jarg2, int jarg3); As an example of passing an inout array (i.e. the target function will both read from and write to the array), consider this C function that swaps a given number of elements in the given arrays: void myArraySwap(int *array1, int *array2, int nitems); Now, we can instruct SWIG to wrap this by %include "arrays_csharp.i" %apply int INOUT[] {int *array1} %apply int INOUT[] {int *array2} This results in the module class method public static void myArraySwap(int[] array1, int[] array2, int nitems) { examplePINVOKE.myArraySwap(array1, array2, nitems); } and intermediate class method [DllImport("example", EntryPoint="CSharp_myArraySwap")] public static extern void myArraySwap([In, Out, MarshalAs(UnmanagedType.LPArray)]int[] jarg1, [In, Out, MarshalAs(UnmanagedType.LPArray)]int[] jarg2, int jarg3); 18.3.3 Managed arrays using pinningIt is also possible to pin a given array in memory (i.e. fix its location in memory), obtain a direct pointer to it, and then pass this pointer to the wrapped C/C++ function. This approach involves no copying, but it makes the work of the garbage collector harder as the managed array object can not be relocated before the fix on the array is released. You should avoid fixing arrays in memory in cases where the control may re-enter the managed side via a callback and/or another thread may produce enough garbage to trigger garbage collection. For more information, see the fixed statement in the C# language reference.
Now let's look at an example using pinning, thus avoiding the CLR making copies of the arrays passed as parameters. The void myArrayCopy(int *sourceArray, int *targetArray, int nitems); We now need to declare the module class method unsafe, as we are using pointers: %csmethodmodifiers myArrayCopy "public unsafe"; Apply the appropriate typemaps to the array parameters: %include "arrays_csharp.i" %apply int FIXED[] {int *sourceArray} %apply int FIXED[] {int *targetArray} Notice that there is no need for separate in, out or inout typemaps as is the case when using P/Invoke default marshalling. As a result, we get the following method in the module class: public unsafe static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) { fixed ( int *swig_ptrTo_sourceArray = sourceArray ) { fixed ( int *swig_ptrTo_targetArray = targetArray ) { { examplePINVOKE.myArrayCopy((IntPtr)swig_ptrTo_sourceArray, (IntPtr)swig_ptrTo_targetArray, nitems); } } } } On the method signature level the only difference to the version using P/Invoke default marshalling is the “unsafe” quantifier, which is required because we are handling pointers. Also the intermediate class method looks a little different from the default marshalling example - the method is expecting an IntPtr as the parameter type. [DllImport("example", EntryPoint="CSharp_myArrayCopy")] public static extern void myArrayCopy(IntPtr jarg1, IntPtr jarg2, int jarg3); 18.4 C# Exceptions
It is possible to throw a C# Exception from C/C++ code. SWIG already provides the framework for throwing C# exceptions if it is able to detect that a C++ exception could be thrown. Automatically detecting that a C++ exception could be thrown is only possible when a C++ exception specification is used, see Exception specifications. The Exception handling with %exception section details the Unfortunately a C# exception cannot simply be thrown from unmanaged code for a variety of reasons. Most notably being that throwing a C# exception results in exceptions being thrown across the C PInvoke interface and C does not understand exceptions. The design revolves around a C# exception being constructed and stored as a pending exception, to be thrown only when the unmanaged code has completed. Implementing this is a tad involved and there are thus some unusual typemap constructs. Some practical examples follow and they should be read in conjunction with the rest of this section.
First some details about the design that must be followed. Each typemap or feature that generates unmanaged code supports an attribute called
The prototypes for the static void SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg); static void SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpExceptionArgumentCodes code, const char *msg, const char *param_name); The first parameter defines which .NET exceptions can be thrown: typedef enum { SWIG_CSharpApplicationException, SWIG_CSharpArithmeticException, SWIG_CSharpDivideByZeroException, SWIG_CSharpIndexOutOfRangeException, SWIG_CSharpInvalidCastException, SWIG_CSharpInvalidOperationException, SWIG_CSharpIOException, SWIG_CSharpNullReferenceException, SWIG_CSharpOutOfMemoryException, SWIG_CSharpOverflowException, SWIG_CSharpSystemException } SWIG_CSharpExceptionCodes; typedef enum { SWIG_CSharpArgumentException, SWIG_CSharpArgumentNullException, SWIG_CSharpArgumentOutOfRangeException, } SWIG_CSharpExceptionArgumentCodes;
where, for example,
The 18.4.1 C# exception example using "check" typemapLets say we have the following simple C++ method: void positivesonly(int number);
and we want to check that the input %module example %typemap(check, canthrow=1) int number %{ if ($1 < 0) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, "only positive numbers accepted", "number"); return $null; } // SWIGEXCODE is a macro used by many other csout typemaps %define SWIGEXCODE "\n if ($modulePINVOKE.SWIGPendingException.Pending)" "\n throw $modulePINVOKE.SWIGPendingException.Retrieve();" %enddef %typemap(csout, excode=SWIGEXCODE) void { $imcall;$excode } %} %inline %{ void positivesonly(int number) { } %} When the following C# code is executed: public class runme { static void Main() { example.positivesonly(-1); } } The exception is thrown: Unhandled Exception: System.ArgumentOutOfRangeException: only positive numbers accepted Parameter name: number in <0x00034> example:positivesonly (int) in <0x0000c> runme:Main () Now let's analyse the generated code to gain a fuller understanding of the typemaps. The generated unmanaged C++ code is: SWIGEXPORT void SWIGSTDCALL CSharp_positivesonly(int jarg1) { int arg1 ; arg1 = (int)jarg1; if (arg1 < 0) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, "only positive numbers accepted", "number"); return ; } positivesonly(arg1); } This largely comes from the “check” typemap. The managed code in the module class is: public class example { public static void positivesonly(int number) { examplePINVOKE.positivesonly(number); if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); } } This comes largely from the “csout” typemap.
The “csout” typemap is the same as the default void “csout” typemap so is not strictly necessary for the example. However, it is shown to demonstrate what managed output code typemaps should contain, that is, a If the “check” typemap did not exist, then the following module class would instead be generated: public class example { public static void positivesonly(int number) { examplePINVOKE.positivesonly(number); } }
Here we see the pending exception checking code is omitted. In fact, the code above would be generated if the %typemap(check) int number %{ if ($1 < 0) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, "only positive numbers accepted", "number"); return $null; } %}
Note that if SWIG detects you have used example.i:21: Warning(845): Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.
Actually it will issue this warning for any function beginning with 18.4.2 C# exception example using %exception
Let's consider a similar, but more common example that throws a C++ exception from within a wrapped function. We can use %exception negativesonly(int value) %{ try { $action } catch (std::out_of_range e) { SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, e.what()); } %} %inline %{ #include <stdexcept> void negativesonly(int value) { if (value >= 0) throw std::out_of_range("number should be negative"); } %}
The generated unmanaged code this time catches the C++ exception and converts it into a C# SWIGEXPORT void SWIGSTDCALL CSharp_negativesonly(int jarg1) { int arg1 ; arg1 = (int)jarg1; try { negativesonly(arg1); } catch (std::out_of_range e) { SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, e.what()); return ; } }
The managed code generated does check for the pending exception as mentioned earlier as the C# version of public static void negativesonly(int value) { examplePINVOKE.negativesonly(value); if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); } 18.4.3 C# exception example using exception specifications
When C++ exception specifications are used, SWIG is able to detect that the method might throw an exception. By default SWIG will automatically generate code to catch the exception and convert it into a managed %typemap(throws, canthrow=1) std::out_of_range { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentException, $1.what(), NULL); return $null; } %inline %{ #include <stdexcept> void evensonly(int input) throw (std::out_of_range) { if (input%2 != 0) throw std::out_of_range("number is not even"); } %} Note that the type for the throws typemap is the type in the exception specification. SWIG generates a try catch block with the throws typemap code in the catch handler. SWIGEXPORT void SWIGSTDCALL CSharp_evensonly(int jarg1) { int arg1 ; arg1 = (int)jarg1; try { evensonly(arg1); } catch(std::out_of_range &_e) { { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentException, (&_e)->what(), NULL); return ; } } } Multiple catch handlers are generated should there be more than one exception specifications declared. 18.4.4 Custom C# ApplicationException example
This example involves a user defined exception. The conventional .NET exception handling approach is to create a custom
The default exception handling is quite easy to use as the %insert(runtime) %{ // Code to handle throwing of C# CustomApplicationException from C/C++ code. // The equivalent delegate to the callback, CSharpExceptionCallback_t, is CustomExceptionDelegate // and the equivalent customExceptionCallback instance is customDelegate typedef void (SWIGSTDCALL* CSharpExceptionCallback_t)(const char *); CSharpExceptionCallback_t customExceptionCallback = NULL; extern "C" SWIGEXPORT void SWIGSTDCALL CustomExceptionRegisterCallback(CSharpExceptionCallback_t customCallback) { customExceptionCallback = customCallback; } // Note that SWIG detects any method calls named starting with // SWIG_CSharpSetPendingException for warning 845 static void SWIG_CSharpSetPendingExceptionCustom(const char *msg) { customExceptionCallback(msg); } %} %pragma(csharp) imclasscode=%{ class CustomExceptionHelper { // C# delegate for the C/C++ customExceptionCallback public delegate void CustomExceptionDelegate(string message); static CustomExceptionDelegate customDelegate = new CustomExceptionDelegate(SetPendingCustomException); [DllImport("$dllimport", EntryPoint="CustomExceptionRegisterCallback")] public static extern void CustomExceptionRegisterCallback(CustomExceptionDelegate customCallback); static void SetPendingCustomException(string message) { SWIGPendingException.Set(new CustomApplicationException(message)); } static CustomExceptionHelper() { CustomExceptionRegisterCallback(customDelegate); } } static CustomExceptionHelper exceptionHelper = new CustomExceptionHelper(); %}
The method stored in the C# delegate instance,
The
The boiler plate code above must be used in addition to a handcrafted // Custom C# Exception class CustomApplicationException : System.ApplicationException { public CustomApplicationException(string message) : base(message) { } } and the SWIG interface code: %typemap(throws, canthrow=1) std::out_of_range { SWIG_CSharpSetPendingExceptionCustom($1.what()); return $null; } %inline %{ void oddsonly(int input) throw (std::out_of_range) { if (input%2 != 1) throw std::out_of_range("number is not odd"); } %}
The “throws” typemap now simply calls our new try { example.oddsonly(2); } catch (CustomApplicationException e) { ... } 18.5 C# DirectorsThe SWIG directors feature adds extra code to the generated C# proxy classes that enable these classes to be used in cross-language polymorphism. Essentially, it enables unmanaged C++ code to call back into managed code for virtual methods so that a C# class can derive from a wrapped C++ class. The following sections provide information on the C# director implementation and contain most of the information required to use the C# directors. However, the Java directors section should also be read in order to gain more insight into directors. 18.5.1 Directors example
Imagine we are wrapping a C++ base class, // file: example.h class Base { public: virtual ~Base() {} virtual unsigned int UIntMethod(unsigned int x) { std::cout << "Base - UIntMethod(" << x << ")" << std::endl; return x; } virtual void BaseBoolMethod(const Base &b, bool flag) {} }; class Caller { public: Caller(): m_base(0) {} ~Caller() { delBase(); } void set(Base *b) { delBase(); m_base = b; } void reset() { m_base = 0; } unsigned int UIntMethodCall(unsigned int x) { return m_base->UIntMethod(x); } private: Base *m_base; void delBase() { delete m_base; m_base = 0; } };
The director feature is turned off by default and the following simple interface file shows how directors are enabled for the class /* File : example.i */ %module(directors="1") example %{ #include "example.h" %} %feature("director") Base; %include "example.h"
The following is a C# class inheriting from public class CSharpDerived : Base { public override uint UIntMethod(uint x) { Console.WriteLine("CSharpDerived - UIntMethod({0})", x); return x; } }
The public class runme { static void Main() { Caller myCaller = new Caller(); // Test pure C++ class using (Base myBase = new Base()) { makeCalls(myCaller, myBase); } // Test director / C# derived class using (Base myBase = new CSharpDerived()) { makeCalls(myCaller, myBase); } } static void makeCalls(Caller myCaller, Base myBase) { myCaller.set(myBase); myCaller.UIntMethodCall(123); myCaller.reset(); } } If the above is run, the output is then: Base - UIntMethod(123) CSharpDerived - UIntMethod(123) 18.5.2 Directors implementation
The previous section demonstrated a simple example where the virtual
Below is the generated C# using System; using System.Runtime.InteropServices; public class Base : IDisposable { private HandleRef swigCPtr; protected bool swigCMemOwn; internal Base(IntPtr cPtr, bool cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = new HandleRef(this, cPtr); } internal static HandleRef getCPtr(Base obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } ~Base() { Dispose(); } public virtual void Dispose() { lock(this) { if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { swigCMemOwn = false; examplePINVOKE.delete_Base(swigCPtr); } swigCPtr = new HandleRef(null, IntPtr.Zero); GC.SuppressFinalize(this); } } public virtual uint UIntMethod(uint x) { uint ret = examplePINVOKE.Base_UIntMethod(swigCPtr, x); return ret; } public virtual void BaseBoolMethod(Base b, bool flag) { examplePINVOKE.Base_BaseBoolMethod(swigCPtr, Base.getCPtr(b), flag); if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); } public Base() : this(examplePINVOKE.new_Base(), true) { SwigDirectorConnect(); } private void SwigDirectorConnect() { if (SwigDerivedClassHasMethod("UIntMethod", swigMethodTypes0)) swigDelegate0 = new SwigDelegateBase_0(SwigDirectorUIntMethod); if (SwigDerivedClassHasMethod("BaseBoolMethod", swigMethodTypes1)) swigDelegate1 = new SwigDelegateBase_1(SwigDirectorBaseBoolMethod); examplePINVOKE.Base_director_connect(swigCPtr, swigDelegate0, swigDelegate1); } private bool SwigDerivedClassHasMethod(string methodName, Type[] methodTypes) { System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, methodTypes); bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(Base)); return hasDerivedMethod; } private uint SwigDirectorUIntMethod(uint x) { return UIntMethod(x); } private void SwigDirectorBaseBoolMethod(IntPtr b, bool flag) { BaseBoolMethod(new Base(b, false), flag); } internal delegate uint SwigDelegateBase_0(uint x); internal delegate void SwigDelegateBase_1(IntPtr b, bool flag); private SwigDelegateBase_0 swigDelegate0; private SwigDelegateBase_1 swigDelegate1; private static Type[] swigMethodTypes0 = new Type[] { typeof(uint) }; private static Type[] swigMethodTypes1 = new Type[] { typeof(Base), typeof(bool) }; }
Everything from the
In the
The last thing that SWIGEXPORT void SWIGSTDCALL CSharp_Base_director_connect(void *objarg, SwigDirector_Base::SWIG_Callback0_t callback0, SwigDirector_Base::SWIG_Callback1_t callback1) { Base *obj = (Base *)objarg; SwigDirector_Base *director = dynamic_cast<SwigDirector_Base *>(obj); if (director) { director->swig_connect_director(callback0, callback1); } } class SwigDirector_Base : public Base, public Swig::Director { public: SwigDirector_Base(); virtual unsigned int UIntMethod(unsigned int x); virtual ~SwigDirector_Base(); virtual void BaseBoolMethod(Base const &b, bool flag); typedef unsigned int (SWIGSTDCALL* SWIG_Callback0_t)(unsigned int); typedef void (SWIGSTDCALL* SWIG_Callback1_t)(void *, unsigned int); void swig_connect_director(SWIG_Callback0_t callbackUIntMethod, SWIG_Callback1_t callbackBaseBoolMethod); private: SWIG_Callback0_t swig_callbackUIntMethod; SWIG_Callback1_t swig_callbackBaseBoolMethod; void swig_init_callbacks(); }; void SwigDirector_Base::swig_connect_director(SWIG_Callback0_t callbackUIntMethod, SWIG_Callback1_t callbackBaseBoolMethod) { swig_callbackUIntMethod = callbackUIntMethod; swig_callbackBaseBoolMethod = callbackBaseBoolMethod; }
Note that for each director class SWIG creates an unmanaged director class for making the callbacks. For example void SwigDirector_Base::BaseBoolMethod(Base const &b, bool flag) { void * jb = 0 ; unsigned int jflag ; if (!swig_callbackBaseBoolMethod) { Base::BaseBoolMethod(b,flag); return; } else { jb = (Base *) &b; jflag = flag; swig_callbackBaseBoolMethod(jb, jflag); } } 18.5.3 Director caveatsThere is a subtle gotcha with directors. If default parameters are used, it is recommended to follow a pattern of always calling a single method in any C# derived class. An example will clarify this and the reasoning behind the recommendation. Consider the following C++ class wrapped as a director class: class Defaults { public: virtual ~Defaults(); virtual void DefaultMethod(int a=-100); };
Recall that C++ methods with default parameters generate overloaded methods for each defaulted parameter, so a C# derived class can be created with two public class CSharpDefaults : Defaults { public override void DefaultMethod() { DefaultMethod(-100); // note C++ default value used } public override void DefaultMethod(int x) { } }
It may not be clear at first, but should a user intend to call 18.6 C# Typemap examples
This section includes a few examples of typemaps. For more examples, you might look at the files “ 18.6.1 Memory management when returning references to member variablesThis example shows how to prevent premature garbage collection of objects when the underlying C++ class returns a pointer or reference to a member variable. The example is a direct equivalent to this Java equivalent. Consider the following C++ code: struct Wheel { int size; Wheel(int sz) : size(sz) {} }; class Bike { Wheel wheel; public: Bike(int val) : wheel(val) {} Wheel& getWheel() { return wheel; } }; and the following usage from C# after running the code through SWIG: Wheel wheel = new Bike(10).getWheel(); Console.WriteLine("wheel size: " + wheel.size); // Simulate a garbage collection System.GC.Collect(); System.GC.WaitForPendingFinalizers(); Console.WriteLine("wheel size: " + wheel.size); Don't be surprised that if the resulting output gives strange results such as… wheel size: 10 wheel size: 135019664
What has happened here is the garbage collector has collected the %typemap(cscode) Wheel %{ // Ensure that the GC doesn't collect any Bike instance set from C# private Bike bikeReference; internal void addReference(Bike bike) { bikeReference = bike; } %} // Add a C# reference to prevent premature garbage collection and resulting use // of dangling C++ pointer. Intended for methods that return pointers or // references to a member variable. %typemap(csout, excode=SWIGEXCODE) Wheel& getWheel { IntPtr cPtr = $imcall;$excode $csclassname ret = null; if (cPtr != IntPtr.Zero) { ret = new $csclassname(cPtr, $owner); ret.addReference(this); } return ret; }
The code in the first typemap gets added to the public class Wheel : IDisposable { ... // Ensure that the GC doesn't collect any Bike instance set from C# private Bike bikeReference; internal void addReference(Bike bike) { bikeReference = bike; } } public class Bike : IDisposable { ... public Wheel getWheel() { IntPtr cPtr = examplePINVOKE.Bike_getWheel(swigCPtr); Wheel ret = null; if (cPtr != IntPtr.Zero) { ret = new Wheel(cPtr, false); ret.addReference(this); } return ret; } }
Note the 18.6.2 Memory management for objects passed to the C++ layerThe example is a direct equivalent to this Java equivalent. Managing memory can be tricky when using C++ and C# proxy classes. The previous example shows one such case and this example looks at memory management for a class passed to a C++ method which expects the object to remain in scope after the function has returned. Consider the following two C++ classes: struct Element { int value; Element(int val) : value(val) {} }; class Container { Element* element; public: Container() : element(0) {} void setElement(Element* e) { element = e; } Element* getElement() { return element; } }; and usage from C++ Container container; Element element(20); container.setElement(&element); cout << "element.value: " << container.getElement()->value << endl; and more or less equivalent usage from C# Container container = new Container(); Element element = new Element(20); container.setElement(element); The C++ code will always print out 20, but the value printed out may not be this in the C# equivalent code. In order to understand why, consider a garbage collection occuring… Container container = new Container(); Element element = new Element(20); container.setElement(element); Console.WriteLine("element.value: " + container.getElement().value); // Simulate a garbage collection System.GC.Collect(); System.GC.WaitForPendingFinalizers(); Console.WriteLine("element.value: " + container.getElement().value);
The temporary element created with public class Container : IDisposable { ... // Ensure that the GC doesn't collect any Element set from C# // as the underlying C++ class stores a shallow copy private Element elementReference; private HandleRef getCPtrAndAddReference(Element element) { elementReference = element; return Element.getCPtr(element); } public void setElement(Element e) { examplePINVOKE.Container_setElement(swigCPtr, getCPtrAndAddReference(e)); } }
The following typemaps will generate the desired code. The 'csin' typemap matches the input parameter type for the %typemap(csin) Element *e "getCPtrAndAddReference($csinput)" %typemap(cscode) Container %{ // Ensure that the GC doesn't collect any Element set from C# // as the underlying C++ class stores a shallow copy private Element elementReference; private HandleRef getCPtrAndAddReference(Element element) { elementReference = element; return Element.getCPtr(element); } %} 18.6.3 Date marshalling using the csin typemap and associated attributes
The NaN Exception example is a simple example of the “javain” typemap and its 'pre' attribute. This example demonstrates how a C++ date class, say class CDate { public: CDate(); CDate(int year, int month, int day); int getYear(); int getMonth(); int getDay(); ... }; struct Action { static int doSomething(const CDate &dateIn, CDate &dateOut); Action(const CDate &date, CDate &dateOut); };
Note that
First let's look at the code that is generated by default, where the C# proxy class public class Action : IDisposable { ... public Action(CDate dateIn, CDate dateOut) : this(examplePINVOKE.new_Action(CDate.getCPtr(dateIn), CDate.getCPtr(dateOut)), true) { if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); } public int doSomething(CDate dateIn, CDate dateOut) { int ret = examplePINVOKE.Action_doSomething(swigCPtr, CDate.getCPtr(dateIn), CDate.getCPtr(dateOut)); if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); return ret; } }
The %typemap(cstype) SWIGTYPE & "$csclassname" %typemap(csin) SWIGTYPE & "$csclassname.getCPtr($csinput)"
where '$csclassname' is translated into the proxy class name, System.DateTime dateIn = new System.DateTime(2011, 4, 13); System.DateTime dateOut = new System.DateTime(); // Note in calls below, dateIn remains unchanged and dateOut // is set to a new value by the C++ call Action action = new Action(dateIn, out dateOut); dateIn = new System.DateTime(2012, 7, 14);
To achieve this mapping, we need to alter the default code generation slightly so that at the C# layer, a %typemap(cstype) const CDate& "System.DateTime" %typemap(csin, pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);" ) const CDate & "$csclassname.getCPtr(temp$csinput)" %typemap(cstype) CDate& "out System.DateTime" %typemap(csin, pre=" CDate temp$csinput = new CDate();", post=" $csinput = new System.DateTime(temp$csinput.getYear()," " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", cshin="out $csinput" ) CDate & "$csclassname.getCPtr(temp$csinput)"
The resulting generated proxy code in the public class Action : IDisposable { ... public int doSomething(System.DateTime dateIn, out System.DateTime dateOut) { CDate tempdateIn = new CDate(dateIn.Year, dateIn.Month, dateIn.Day); CDate tempdateOut = new CDate(); try { int ret = examplePINVOKE.Action_doSomething(swigCPtr, CDate.getCPtr(tempdateIn), CDate.getCPtr(tempdateOut)); if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); return ret; } finally { dateOut = new System.DateTime(tempdateOut.getYear(), tempdateOut.getMonth(), tempdateOut.getDay(), 0, 0, 0); } } static private IntPtr SwigConstructAction(System.DateTime dateIn, out System.DateTime dateOut) { CDate tempdateIn = new CDate(dateIn.Year, dateIn.Month, dateIn.Day); CDate tempdateOut = new CDate(); try { return examplePINVOKE.new_Action(CDate.getCPtr(tempdateIn), CDate.getCPtr(tempdateOut)); } finally { dateOut = new System.DateTime(tempdateOut.getYear(), tempdateOut.getMonth(), tempdateOut.getDay(), 0, 0, 0); } } public Action(System.DateTime dateIn, out System.DateTime dateOut) : this(Action.SwigConstructAction(dateIn, out dateOut), true) { if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve(); } } A few things to note:
So far we have considered the date as an input only and an output only type. Now let's consider void addYears(CDate *pDate, int years) { *pDate = CDate(pDate->getYear() + years, pDate->getMonth(), pDate->getDay()); }
If usage of System.DateTime christmasEve = new System.DateTime(2000, 12, 24); example.addYears(ref christmasEve, 10); // christmasEve now contains 2010-12-24
will be possible with the following %typemap(cstype, out="System.DateTime") CDate * "ref System.DateTime" %typemap(csin, pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);", post=" $csinput = new System.DateTime(temp$csinput.getYear()," " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", cshin="ref $csinput" ) CDate * "$csclassname.getCPtr(temp$csinput)" Globals are wrapped by the module class and for a module called example, the typemaps result in the following code: public class example { public static void addYears(ref System.DateTime pDate, int years) { CDate temppDate = new CDate(pDate.Year, pDate.Month, pDate.Day); try { examplePINVOKE.addYears(CDate.getCPtr(temppDate), years); } finally { pDate = new System.DateTime(temppDate.getYear(), temppDate.getMonth(), temppDate.getDay(), 0, 0, 0); } } ... }
The following typemap is the same as the previous but demonstrates how a using block can be used for the temporary variable. The only change to the previous typemap is the introduction of the 'terminator' attribute to terminate the %typemap(csin, pre=" using (CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day)) {", post=" $csinput = new System.DateTime(temp$csinput.getYear()," " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", terminator=" } // terminate temp$csinput using block", cshin="ref $csinput" ) CDate * "$csclassname.getCPtr(temp$csinput)" void subtractYears(CDate *pDate, int years) { *pDate = CDate(pDate->getYear() - years, pDate->getMonth(), pDate->getDay()); }
The resulting generated code shows the termination of the public class example { public static void subtractYears(ref System.DateTime pDate, int years) { using (CDate temppDate = new CDate(pDate.Year, pDate.Month, pDate.Day)) { try { examplePINVOKE.subtractYears(CDate.getCPtr(temppDate), years); } finally { pDate = new System.DateTime(temppDate.getYear(), temppDate.getMonth(), temppDate.getDay(), 0, 0, 0); } } // terminate temppDate using block } ... } 18.6.4 A date example demonstrating marshalling of C# properties
The previous section looked at converting a C++ date class to CDate ImportantDate = CDate(1999, 12, 31);
The aim is to use example.ImportantDate = new System.DateTime(2000, 11, 22); System.DateTime importantDate = example.ImportantDate; Console.WriteLine("Important date: " + importantDate);
When SWIG wraps a variable that is a class/struct/union, it is wrapped using a pointer to the type for the reasons given in Stucture data members. The typemap type required is thus %typemap(cstype, out="System.DateTime") CDate * "ref System.DateTime" %typemap(csin, pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);", post=" $csinput = new System.DateTime(temp$csinput.getYear()," " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", cshin="ref $csinput" ) CDate * "$csclassname.getCPtr(temp$csinput)" %typemap(csvarin, excode=SWIGEXCODE2) CDate * %{ /* csvarin typemap code */ set { CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day); $imcall;$excode } %} %typemap(csvarout, excode=SWIGEXCODE2) CDate * %{ /* csvarout typemap code */ get { IntPtr cPtr = $imcall; CDate tempDate = (cPtr == IntPtr.Zero) ? null : new CDate(cPtr, $owner);$excode return new System.DateTime(tempDate.getYear(), tempDate.getMonth(), tempDate.getDay(), 0, 0, 0); } %} For a module called example, the typemaps result in the following code: public class example { public static System.DateTime ImportantDate { /* csvarin typemap code */ set { CDate tempvalue = new CDate(value.Year, value.Month, value.Day); examplePINVOKE.ImportantDate_set(CDate.getCPtr(tempvalue)); } /* csvarout typemap code */ get { IntPtr cPtr = examplePINVOKE.ImportantDate_get(); CDate tempDate = (cPtr == IntPtr.Zero) ? null : new CDate(cPtr, false); return new System.DateTime(tempDate.getYear(), tempDate.getMonth(), tempDate.getDay(), 0, 0, 0); } } ... } Some points to note:
18.6.5 Turning wrapped classes into partial classes
C# supports the notion of partial classes whereby a class definition can be split into more than one file. It is possible to turn the wrapped C++ class into a partial C# class using the class ExtendMe { public: int Part1() { return 1; } }; The default C# proxy class generated is: public class ExtendMe : IDisposable { ... public int Part1() { ... } } The default csclassmodifiers typemap shipped with SWIG is %typemap(csclassmodifiers) SWIGTYPE "public class"
Note that the type used is the special catch all type %typemap(csclassmodifiers) ExtendMe "public partial class" The C# proxy class becomes a partial class: public partial class ExtendMe : IDisposable { ... public int Part1() { ... } } You can then of course declare another part of the partial class elsewhere, for example: public partial class ExtendMe : IDisposable { public int Part2() { return 2; } } and compile the following code: ExtendMe em = new ExtendMe(); Console.WriteLine("part1: {0}", em.Part1()); Console.WriteLine("part2: {0}", em.Part2());
demonstrating that the class contains methods calling both unmanaged code - 18.6.6 Extending proxy classes with additional C# code
The previous example showed how to use partial classes to add functionality to a generated C# proxy class. It is also possible to extend a wrapped struct/class with C/C++ code by using the %extend directive. A third approach is to add some C# methods into the generated proxy class with the %typemap(cscode) ExtendMe %{ public int Part3() { return 3; } %} The generated C# proxy class will instead be: public class ExtendMe : IDisposable { ... public int Part3() { return 3; } public int Part1() { ... } } 19 SWIG and ChickenThis chapter describes SWIG's support of CHICKEN. CHICKEN is a Scheme-to-C compiler supporting most of the language features as defined in the Revised^5 Report on Scheme. Its main attributes are that it
When confronted with a large C library, CHICKEN users can use SWIG to generate CHICKEN wrappers for the C library. However, the real advantages of using SWIG with CHICKEN are its support for C++ – object-oriented code is difficult to wrap by hand in CHICKEN – and its typed pointer representation, essential for C and C++ libraries involving structures or classes. 19.1 PreliminariesCHICKEN support was introduced to SWIG in version 1.3.18. SWIG relies on some recent additions to CHICKEN, which are only present in releases of CHICKEN with version number greater than or equal to 1.89. To use a chicken version between 1.40 and 1.89, see the Garbage collection section below. You may want to look at any of the examples in Examples/chicken/ or Examples/GIFPlot/Chicken for the basic steps to run SWIG CHICKEN. 19.1.1 Running SWIG in C modeTo run SWIG CHICKEN in C mode, use the -chicken option. % swig -chicken example.i
To allow the wrapper to take advantage of future CHICKEN code generation improvements, part of the wrapper is direct CHICKEN function calls ( % chicken example.scm -output-file oexample.c
So for the C mode of SWIG CHICKEN, 19.1.2 Running SWIG in C++ modeTo run SWIG CHICKEN in C++ mode, use the -chicken -c++ option. % swig -chicken -c++ example.i
This will generate % chicken example.scm -output-file oexample.c
So for the C++ mode of SWIG CHICKEN, 19.2 Code Generation19.2.1 Naming Conventions
Given a C variable, function or constant declaration named
You may control what the CHICKEN identifier will be by using the 19.2.2 ModulesThe name of the module must be declared one of two ways:
The generated example.scm file then exports
CHICKEN will be able to access the module using the 19.2.3 Constants and VariablesConstants may be created using any of the four constructs in the interface file:
In all cases, the constants may be accessed from within CHICKEN using the form
Variables are accessed using the full parameter form. For example, to set the C variable “int my_variable;”, use the Scheme form
The 19.2.4 Functions
C functions declared in the SWIG interface file will have corresponding CHICKEN Scheme procedures. For example, the C function “int sqrt(double x);” will be available using the Scheme form
A function may return more than one value by using the 19.2.5 ExceptionsThe SWIG chicken module has support for exceptions thrown from C or C++ code to be caught in scheme. See Exception handling with %exception for more information about declaring exceptions in the interface file.
Chicken supports both the The following simple module %module exception_test %inline %{ void test_throw(int i) throws (int) { if (i == 1) throw 15; } %} could be run with (handle-exceptions exvar (if (= exvar 15) (print "Correct!") (print "Threw something else " exvar)) (test-throw 1)) 19.3 TinyCLOSThe author of TinyCLOS, Gregor Kiczales, describes TinyCLOS as: “Tiny CLOS is a Scheme implementation of a `kernelized' CLOS, with a metaobject protocol. The implementation is even simpler than the simple CLOS found in `The Art of the Metaobject Protocol,' weighing in at around 850 lines of code, including (some) comments and documentation.” Almost all good Scheme books describe how to use metaobjects and generic procedures to implement an object-oriented Scheme system. Please consult a Scheme book if you are unfamiliar with the concept. CHICKEN has a modified version of TinyCLOS, which SWIG CHICKEN uses if the -proxy argument is given. If -proxy is passed, then the generated example.scm file will contain TinyCLOS class definitions. A class named Foo is declared as <Foo>, and each member variable is allocated a slot. Member functions are exported as generic functions. Primitive symbols and functions (the interface that would be presented if -proxy was not passed) are hidden and no longer accessible. If the -unhideprimitive command line argument is passed to SWIG, then the primitive symbols will be available, but each will be prefixed by the string “primitive:” The exported symbol names can be controlled with the -closprefix and -useclassprefix arguments. If -useclassprefix is passed to SWIG, every member function will be generated with the class name as a prefix. If the -closprefix mymod: argument is passed to SWIG, then the exported functions will be prefixed by the string “mymod:”. If -useclassprefix is passed, -closprefix is ignored. 19.4 Linkage
Please refer to CHICKEN - A practical and portable Scheme system - User's manual for detailed help on how to link object files to create a CHICKEN Scheme program. Briefly, to link object files, be sure to add
Each scheme file that is generated by SWIG contains 19.4.1 Static binary or shared library linked at compile timeWe can easily use csc to build a static binary. $ swig -chicken example.i $ csc -v example.scm example_impl.c example_wrap.c test_script.scm -o example $ ./example
Similar to the above, any number of $ swig -chicken example.i $ csc -sv example.scm example_wrap.c example_impl.c -o example.so
The $ csc -v test_script.scm -lexample
An alternative is that the test_script.scm can have the code 19.4.2 Building chicken extension libraries
Building a shared library like in the above section only works if the library is linked at compile time with a script containing
First, SWIG accepts a $ csc -sv modname.scm modname_wrap.c modname_impl.c -o modname.so
This library can then be loaded by scheme code with the
Another alternative is to run SWIG normally and create a scheme file that contains (declare (uses mod1)) (declare (uses mod2)) Which would then be compiled with $ swig -chicken mod1.i $ swig -chicken mod2.i $ csc -sv mod_load.scm mod1.scm mod2.scm mod1_wrap.c mod2_wrap.c mod1_impl.c mod2_impl.c -o mod.so
Then the extension library can be loaded with
In either method, the files that are compiled into the shared library could also be packaged into an egg. The
See the 19.4.3 Linking multiple SWIG modules with TinyCLOS
Linking together multiple modules that share type information using the
One option is to override the automatic generation of
The other option is to use the second idea in the above section. Compile all the modules normally, without any 19.5 Typemaps
The Chicken module handles all types via typemaps. This information is read from 19.6 PointersFor pointer types, SWIG uses CHICKEN tagged pointers. A tagged pointer is an ordinary CHICKEN pointer with an extra slot for a void *. With SWIG CHICKEN, this void * is a pointer to a type-info structure. So each pointer used as input or output from the SWIG-generated CHICKEN wrappers will have type information attached to it. This will let the wrappers correctly determine which method should be called according to the object type hierarchy exposed in the SWIG interface files.
To construct a Scheme object from a C pointer, the wrapper code calls the function
To get the pointer represented by a CHICKEN tagged pointer, the wrapper code calls the function 19.6.1 Garbage collection
If the owner flag passed to
In situations where a C or C++ function will assume ownership of a pointer, and thus chicken should no longer garbage collect it, SWIG provides the
Adding a finalizer function from C code was added to chicken in the 1.89 release, so garbage collection does not work for chicken versions below 1.89. If you would like the SWIG generated code to work with chicken 1.40 to 1.89, pass the 19.7 Unsupported features and known problems
19.7.1 TinyCLOS problems with Chicken version <= 1.92In Chicken versions equal to or below 1.92, TinyCLOS has a limitation such that generic methods do not properly work on methods with different number of specializers: TinyCLOS assumes that every method added to a generic function will have the same number of specializers. SWIG generates functions with different lengths of specializers when C/C++ functions are overloaded. For example, the code class Foo {}; int foo(int a, Foo *b); int foo(int a); will produce scheme code (define-method (foo (arg0 <top>) (arg1 <Foo>)) (call primitive function)) (define-method (foo (arg0 <top>)) (call primitive function))
Using unpatched TinyCLOS, the second
There are three solutions to this. The easist is to upgrade to the latest Chicken version. Otherwise, the file 20 SWIG and GuileThis section details guile-specific support in SWIG. 20.1 Meaning of "Module"There are three different concepts of “module” involved, defined separately for SWIG, Guile, and Libtool. To avoid horrible confusion, we explicitly prefix the context, e.g., “guile-module”. 20.2 Using the SCM or GH Guile APIThe guile module can currently export wrapper files that use the guile GH interface or the SCM interface. This is controlled by an argument passed to swig. The “-gh” argument causes swig to output GH code, and the “-scm” argument causes swig to output SCM code. Right now the “-scm” argument is the default. The “-scm” wrapper generation assumes a guile version >= 1.6 and has several advantages over the “-gh” wrapper generation including garbage collection and GOOPS support. The “-gh” wrapper generation can be used for older versions of guile. The guile GH wrapper code generation is depreciated and the SCM interface is the default. The SCM and GH interface differ greatly in how they store pointers and have completely different run-time code. See below for more info. The GH interface to guile is deprecated. Read more about why in the Guile manual. The idea of the GH interface was to provide a high level API that other languages and projects could adopt. This was a good idea, but didn't pan out well for general development. But for the specific, minimal uses that the SWIG typemaps put the GH interface to use is ideal for using a high level API. So even though the GH interface is depreciated, SWIG will continue to use the GH interface and provide mappings from the GH interface to whatever API we need. We can maintain this mapping where guile failed because SWIG uses a small subset of all the GH functions which map easily. All the guile typemaps like typemaps.i and std_vector.i will continue to use the GH functions to do things like create lists of values, convert strings to integers, etc. Then every language module will define a mapping between the GH interface and whatever custom API the language uses. This is currently implemented by the guile module to use the SCM guile API rather than the GH guile API. For example, here are some of the current mapping file for the SCM API #define gh_append2(a, b) scm_append(scm_listify(a, b, SCM_UNDEFINED)) #define gh_apply(a, b) scm_apply(a, b, SCM_EOL) #define gh_bool2scm SCM_BOOL #define gh_boolean_p SCM_BOOLP #define gh_car SCM_CAR #define gh_cdr SCM_CDR #define gh_cons scm_cons #define gh_double2scm scm_make_real ... This file is parsed by SWIG at wrapper generation time, so every reference to a gh_ function is replaced by a scm_ function in the wrapper file. Thus the gh_ function calls will never be seen in the wrapper; the wrapper will look exactly like it was generated for the specific API. Currently only the guile language module has created a mapping policy from gh_ to scm_, but there is no reason other languages (like mzscheme or chicken) couldn't also use this. If that happens, there is A LOT less code duplication in the standard typemaps. 20.3 LinkageGuile support is complicated by a lack of user community cohesiveness, which manifests in multiple shared-library usage conventions. A set of policies implementing a usage convention is called a linkage. 20.3.1 Simple Linkage
The default linkage is the simplest; nothing special is done. In this case the function
(define my-so (dynamic-link “./example.so”))
(dynamic-call “SWIG_init” my-so) ; make SWIG bindings
;; Scheme definitions can go here
Newer Guile versions provide a shorthand for (module-export! (current-module) (list sym))) (current-module))
SWIG can also generate this Scheme stub (from
(The
If you want to include several SWIG modules, you would need to rename 20.3.2 Passive LinkagePassive linkage is just like simple linkage, but it generates an initialization function whose name is derived from the module and package name (see below). You should use passive linkage rather than simple linkage when you are using multiple modules. 20.3.3 Native Guile Module Linkage
SWIG can also generate wrapper code that does all the Guile module declarations on its own if you pass it the
The module name is set with the You can use this linkage in several ways:
;; create new module and put bindings there: (dynamic-call “scm_init_my_modules_foo_module” my-so) Newer Guile versions have a shorthand procedure for this: (load-extension “./foo.so” “scm_init_my_modules_foo_module”) 20.3.4 Old Auto-Loading Guile Module Linkage
Guile used to support an autoloading facility for object-code modules. This support has been marked deprecated in version 1.4.1 and is going to disappear sooner or later. SWIG still supports building auto-loading modules if you pass it the
Auto-loading worked like this: Suppose a module with name
When invoked with the 20.3.5 Hobbit4D Linkage
The only other linkage supported at this time creates shared object libraries suitable for use by hobbit's swig -guile -package my/lib foo.i swig -guile -package my/lib -module foo foo.i
would create module 20.4 Underscore FoldingUnderscores are converted to dashes in identifiers. Guile support may grow an option to inhibit this folding in the future, but no one has complained so far.
You can use the SWIG directives 20.5 Typemaps
The Guile module handles all types via typemaps. This information is read from
A function returning Multiple values can be passed up to Scheme in one of three ways:
(divide 35 17) body...)
In See also the “multivalue” example. Constants are exported as a function that returns the value. The %feature(“constasvar”) can be applied to any constant, immutable variable, or enum. Instead of exporting the constant as a function that must be called, the constant will appear as a scheme variable. See Features and the %feature directive for info on how to apply the %feature. 20.6 Representation of pointers as smobs
For pointer types, SWIG uses Guile smobs. SWIG smobs print like this:
To construct a Scheme object from a C pointer, the wrapper code calls the function 20.6.1 GH SmobsIn earlier versions of SWIG, C pointers were represented as Scheme strings containing a hexadecimal rendering of the pointer value and a mangled type name. As Guile allows registering user types, so-called “smobs” (small objects), a much cleaner representation has been implemented now. The details will be discussed in the following. A smob is a cons cell where the lower half of the CAR contains the smob type tag, while the upper half of the CAR and the whole CDR are available. Every module creates its own smob type in the clientdata field of the module. So the lower 16 bits of the car of the smob store the tag and the upper 16 bits store the index this type is in the array. We can then, given a smob, find its swig_type_info struct by using the tag (lower 16 bits of car) to find which module this type is in (since each tag is unique for the module). Then we use the upper 16 bits to index into the array of types attached to this module. Looking up the module from the tag is worst case O(# of modules) but average case O(1). This is because the modules are stored in a circularly linked list, and when we start searching the modules for the tag, we start looking with the module that the function doing the lookup is in. SWIG_Guile_ConvertPtr() takes as its first argument the swig_module_info * of the calling function, which is where we start comparing tags. Most types will be looked up in the same module that created them, so the first module we check will most likely be correct. Once we have a swig_type_info structure, we loop through the linked list of casts, using pointer comparisons. 20.6.2 SCM SmobsThe SCM interface (using the “-scm” argument to swig) uses swigrun.swg. The whole type system, when it is first initialized, creates two smobs named “swig” and “collected_swig”. The swig smob is used for non-garbage collected smobs, while the collected_swig smob is used as described below. Each smob has the same format, which is a double cell created by SCM_NEWSMOB2() The first word of data is the pointer to the object and the second word of data is the swig_type_info * structure describing this type. This is a lot easier than the GH interface above because we can store a pointer to the type info structure right in the type. With the GH interface, there was not enough room in the smob to store two whole words of data so we needed to store part of the “swig_type_info address” in the smob tag. If a generated GOOPS module has been loaded, smobs will be wrapped by the corresponding GOOPS class. 20.6.3 Garbage CollectionGarbage collection is a feature of the new SCM interface, and it is automatically included if you pass the “-scm” flag to swig. Thus the swig garbage collection support requires guile >1.6. Garbage collection works like this. Every swig_type_info structure stores in its clientdata field a pointer to the destructor for this type. The destructor is the generated wrapper around the delete function. So swig still exports a wrapper for the destructor, it just does not call scm_c_define_gsubr() for the wrapped delete function. So the only way to delete an object is from the garbage collector, since the delete function is not available to scripts. How swig determines if a type should be garbage collected is exactly like described in Object ownership and %newobject in the SWIG manual. All typemaps use an $owner var, and the guile module replaces $owner with 0 or 1 depending on feature:new. 20.7 Exception Handling
SWIG code calls MAP(SWIG_MemoryError, "swig-memory-error"); MAP(SWIG_IOError, "swig-io-error"); MAP(SWIG_RuntimeError, "swig-runtime-error"); MAP(SWIG_IndexError, "swig-index-error"); MAP(SWIG_TypeError, "swig-type-error"); MAP(SWIG_DivisionByZero, "swig-division-by-zero"); MAP(SWIG_OverflowError, "swig-overflow-error"); MAP(SWIG_SyntaxError, "swig-syntax-error"); MAP(SWIG_ValueError, "swig-value-error"); MAP(SWIG_SystemError, "swig-system-error"); The default when not specified here is to use “swig-error”. See Lib/exception.i for details. 20.8 Procedure documentation
If invoked with the command-line option
SWIG can generate documentation strings in three formats, which are selected via the command-line option
You need to register the generated documentation file with Guile like this: (use-modules (ice-9 documentation)) (set! documentation-files (cons "file" documentation-files))
Documentation strings can be configured using the Guile-specific typemap argument 20.9 Procedures with setters
For global variables, SWIG creates a single wrapper procedure
If invoked with the command-line option
If invoked with the command-line option 20.10 GOOPS Proxy ClassesSWIG can also generate classes and generic functions for use with Guile's Object-Oriented Programming System (GOOPS). GOOPS is a sophisticated object system in the spirit of the Common Lisp Object System (CLOS).
GOOPS support is only available with the new SCM interface (enabled with the The generated file will contain definitions of GOOPS classes mimicking the C++ class hierarchy.
Enabling GOOPS support implies
If class Foo { public: Foo(int i) : a(i) {} int a; int getMultBy(int i) { return a * i; } Foo getFooMultBy(int i) { return Foo(a * i); } }; Foo getFooPlus(int i) { return Foo(a + i); }
will produce (if (define-class <Foo> (<swig>) (a #:allocation #:swig-virtual #:slot-ref primitive:Foo-a-get #:slot-set! primitive:Foo-a-set) #:metaclass <swig-metaclass> #:new-function primitive:new-Foo ) (define-method (getMultBy (swig_smob <Foo>) i) (primitive:Foo-getMultBy (slot-ref swig_smob 'smob) i)) (define-method (getFooMultBy (swig_smob <Foo>) i) (make <Foo> #:init-smob (primitive:Foo-getFooMultBy (slot-ref swig_smob 'smob) i))) (define-method (getFooPlus i) (make <Foo> #:init-smob (primitive:getFooPlus i))) (export <Foo> getMultBy getFooMultBy getFooPlus )
and will produce (if (define-class <Foo> (<swig>) (a #:allocation #:swig-virtual #:slot-ref primitive:Foo-a-get #:slot-set! primitive:Foo-a-set #:accessor a) #:metaclass <swig-metaclass> #:new-function primitive:new-Foo ) (define-method (getMultBy (swig_smob <Foo>) i) (primitive:Foo-getMultBy (slot-ref swig_smob 'smob) i)) (define-method (getFooMultBy (swig_smob <Foo>) i) (make <Foo> #:init-smob (primitive:Foo-getFooMultBy (slot-ref swig_smob 'smob) i))) (define-method (getFooPlus i) (make <Foo> #:init-smob (primitive:getFooPlus i))) (export <Foo> a getMultBy getFooMultBy getFooPlus ) which can then be used by this code ;; not using getters and setters (define foo (make <Foo> #:args '(45))) (slot-ref foo 'a) (slot-set! foo 'a 3) (getMultBy foo 4) (define foo2 (getFooMultBy foo 7)) (slot-ref foo 'a) (slot-ref (getFooPlus foo 4) 'a) ;; using getters and setters (define foo (make <Foo> #:args '(45))) (a foo) (set! (a foo) 5) (getMultBy foo 4) (a (getFooMultBy foo 7))
Notice that constructor arguments are passed as a list after the Also note that the order the declarations occur in the .i file make a difference. For example, %module test %{ #include "foo.h" %} %inline %{ int someFunc(Foo &a) { ... } %} %include "foo.h"
This is a valid SWIG file it will work as you think it will for primitive support, but the generated GOOPS file will be broken. Since the ;;... (define-method (someFunc (swig_smob <Foo>)) (primitive:someFunc (slot-ref swig_smob 'smob))) ;;... (define-class <Foo> (<swig>) ;;... ) ;;...
Notice that <Foo> is used before it is defined. The fix is to just put the 20.10.1 Naming Issues
As you can see in the example above, there are potential naming conflicts. The default exported accessor for the
Two guile-modules are created by SWIG. The first module contains the primitive definitions of all the wrapped functions and variables, and is located either in the _wrap.cxx file (with
Because of the naming conflicts, you can't in general use both the (use-modules ((Test-primitive) #:renamer (symbol-prefix-proc 'primitive:))) (use-modules ((Test) #:renamer (symbol-prefix-proc 'goops:))) TODO: Renaming class name prefixes? 20.10.2 Linking
The guile-modules generated above all need to be linked together. GOOPS support requires either passive or module linkage. The exported GOOPS guile-module will be the name of the swig-module and should be located in a file called Module.scm. This should be installed on the autoload path for guile, so that This breaks up into three cases
Produces the following code at the top of the generated GOOPS guile-module (with the ;; %goops directive goes here (load-extension “./foo.so” “scm_init_my_modules_foo_module”) (use-modules (oop goops) (Swig common))
// only include the following definition if (my modules foo) cannot // be loaded automatically %goops %{ (primitive-load "/path/to/foo-primitive.scm") (primitive-load "/path/to/Swig/common.scm") %} Produces the following code at the top of the generated GOOPS guile-module (define-module (my modules foo)) ;; %goops directive goes here (if any) (primitive-load “/path/to/foo-primitive.scm”) (primitive-load “/path/to/Swig/common.scm”) (use-modules (oop goops) (Swig common)) (use-modules ((my modules foo-primitive) :renamer (symbol-prefix-proc 'primitive:)))
Produces the following code at the top of the generated GOOPS guile-module (define-module (my modules foo)) ;; %goops directive goes here (if any) (load-extension “./foo.so” “scm_init_my_modules_foo_module”) (use-modules (oop goops) (Swig common)) (use-modules ((my modules foo-primitive) :renamer (symbol-prefix-proc 'primitive:)))
(Swig common): The generated GOOPS guile-module also imports definitions from the (Swig common) guile-module. This module is included with SWIG and should be installed by SWIG into the autoload path for guile (based on the configure script and whatever arguments are passed). If it is not, then the
Multiple Modules: Type dependencies between modules is supported. For example, if 21 SWIG and JavaThis chapter describes SWIG's support of Java. It covers most SWIG features, but certain low-level details are covered in less depth than in earlier chapters. 21.1 OverviewThe 100% Pure Java effort is a commendable concept, however in the real world programmers often either need to re-use their existing code or in some situations want to take advantage of Java but are forced into using some native (C/C++) code. The Java extension to SWIG makes it very easy to plumb in existing C/C++ code for access from Java, as SWIG writes the Java Native Interface (JNI) code for you. It is different to using the 'javah' tool as SWIG will wrap existing C/C++ code, whereas javah takes 'native' Java function declarations and creates C/C++ function prototypes. SWIG wraps C/C++ code using Java proxy classes and is very useful if you want to have access to large amounts of C/C++ code from Java. If only one or two JNI functions are needed then using SWIG may be overkill. SWIG enables a Java program to easily call into C/C++ code from Java. Historically, SWIG was not able to generate any code to call into Java code from C++. However, SWIG now supports full cross language polymorphism and code is generated to call up from C++ to Java when wrapping C++ virtual methods. Java is one of the few non-scripting language modules in SWIG. As SWIG utilizes the type safety that the Java language offers, it takes a somewhat different approach to that used for scripting languages. In particular runtime type checking and the runtime library are not used by Java. This should be borne in mind when reading the rest of the SWIG documentation. This chapter on Java is relatively self contained and will provide you with nearly everything you need for using SWIG and Java. However, the “SWIG Basics” chapter will be a useful read in conjunction with this one. This chapter starts with a few practicalities on running SWIG and compiling the generated code. If you are looking for the minimum amount to read, have a look at the sections up to and including the tour of basic C/C++ wrapping section which explains how to call the various C/C++ code constructs from Java. Following this section are details of the C/C++ code and Java classes that SWIG generates. Due to the complexities of C and C++ there are different ways in which C/C++ code could be wrapped and called from Java. SWIG is a powerful tool and the rest of the chapter details how the default code wrapping can be tailored. Various customisation tips and techniques using SWIG directives are covered. The latter sections cover the advanced techniques of using typemaps for complete control of the wrapping process. 21.2 Preliminaries
SWIG 1.1 works with JDKs from JDK 1.1 to JDK1.4 (Java 2 SDK1.4) and should also work with any later versions. Given the choice, you should probably use the latest version of Sun's JDK. The SWIG Java module is known to work using Sun's JVM on Solaris, Linux and the various flavours of Microsoft Windows including Cygwin. The Kaffe JVM is known to give a few problems and at the time of writing was not a fully fledged JVM with full JNI support. The generated code is also known to work on vxWorks using WindRiver's PJava 3.1. The best way to determine whether your combination of operating system and JDK will work is to test the examples and test-suite that comes with SWIG. Run The Java module requires your system to support shared libraries and dynamic loading. This is the commonly used method to load JNI code so your system will more than likely support this. 21.2.1 Running SWIGSuppose that you defined a SWIG module such as the following: /* File: example.i */ %module test %{ #include "stuff.h" %} int fact(int n);
To build a Java module, run SWIG using the %swig -java example.i
If building C++, add the $ swig -c++ -java example.i
This creates two different files; a C/C++ source file
The name of the wrapper file is derived from the name of the input file. For example, if the input file is
The module name, specified with The following sections have further practical examples and details on how you might go about compiling and using the generated files. 21.2.2 Additional Commandline OptionsThe following table list the additional commandline options available for the Java module. They can also be seen by using: swig -java -help
Their use will become clearer by the time you have finished reading this section on SWIG and Java. 21.2.3 Getting the right header files
In order to compile the C/C++ wrappers, the compiler needs the /usr/java/include /usr/java/include/<operating_system> The exact location may vary on your machine, but the above locations are typical. 21.2.4 Compiling a dynamic moduleThe JNI code exists in a dynamic module or shared library (DLL on Windows) and gets loaded by the JVM. To build a shared library file, you need to compile your module in a manner similar to the following (shown for Solaris): $ swig -java example.i $ gcc -c example_wrap.c -I/usr/java/include -I/usr/java/include/solaris $ ld -G example_wrap.o -o libexample.so
The exact commands for doing this vary from platform to platform. However, SWIG tries to guess the right options when it is installed. Therefore, you may want to start with one of the examples in the
Important
The name of the shared library output file is important. If the name of your SWIG module is “ 21.2.5 Using your module
To load your shared native library module in Java, simply use Java's // runme.java public class runme { static { System.loadLibrary("example"); } public static void main(String argv[]) { System.out.println(example.fact(4)); } } Compile all the Java files and run: $ javac *.java $ java runme 24 $ If it doesn't work have a look at the following section which discusses problems loading the shared library. 21.2.6 Dynamic linking problems
As shown in the previous section the code to load a native library (shared library) is You may get an exception similar to this: $ java runme Exception in thread "main" java.lang.UnsatisfiedLinkError: no example in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1312) at java.lang.Runtime.loadLibrary0(Runtime.java:749) at java.lang.System.loadLibrary(System.java:820) at runme.<clinit>(runme.java:5)
The most common cause for this is an incorrect naming of the native library for the name passed to the
Another common reason for the native library not loading is because it is not in your path. On Windows make sure the path environment variable contains the path to the native library. On Unix make sure that your LD_LIBRARY_PATH contains the path to the native library. Adding paths to LD_LIBRARY_PATH can slow down other programs on your system so you may want to consider alternative approaches. For example you could recompile your native library with extra path information using The native library will also not load if there are any unresolved symbols in the compiled C/C++ code. The following exception is indicative of this: $ java runme Exception in thread "main" java.lang.UnsatisfiedLinkError: libexample.so: undefined symbol: fact at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java, Compiled Code) at java.lang.ClassLoader.loadLibrary(ClassLoader.java, Compiled Code) at java.lang.Runtime.loadLibrary0(Runtime.java, Compiled Code) at java.lang.System.loadLibrary(System.java, Compiled Code) at runme.<clinit>(runme.java:5) $ This error usually indicates that you forgot to include some object files or libraries in the linking of the native library file. Make sure you compile both the SWIG wrapper file and the code you are wrapping into the native library file. If you forget to compile and link in the SWIG wrapper file into your native library file, you will get a message similar to the following: $ java runme Exception in thread "main" java.lang.UnsatisfiedLinkError: exampleJNI.gcd(II)I at exampleJNI.gcd(Native Method) at example.gcd(example.java:12) at runme.main(runme.java:18)
where In summary, ensure that you are using the correct C/C++ compiler and linker combination and options for successful native library loading. If you are using the examples that ship with SWIG, then the Examples/Makefile must have these set up correctly for your system. The SWIG installation package makes a best attempt at getting these correct but does not get it right 100% of the time. The SWIG Wiki also has some settings for commonly used compiler and operating system combinations. The following section also contains some C++ specific linking problems and solutions. 21.2.7 Compilation problems and compiling with C++On most machines, shared library files should be linked using the C++ compiler. For example: % swig -c++ -java example.i % g++ -c -fpic example.cxx % g++ -c -fpic example_wrap.cxx -I/usr/java/j2sdk1.4.1/include -I/usr/java/ j2sdk1.4.1/include/linux % g++ -shared example.o example_wrap.o -o libexample.so
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 % swig -c++ -java example.i % CC -c example.cxx % CC -c example_wrap.cxx -I/usr/java/include -I/usr/java/include/solaris % CC -G example.o example_wrap.o -L/opt/SUNWspro/lib -o libexample.so -lCrun
If you aren't entirely sure about the linking for C++, you might look at an existing C++ program. On many Unix machines, the $ 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) $ Finally make sure the version of JDK header files matches the version of Java that you are running as incompatibilities could lead to compilation problems or unpredictable behaviour. 21.2.8 Building on WindowsBuilding on Windows is roughly similar to the process used with Unix. You will want to produce a DLL that can be loaded by the Java Virtual Machine. This section covers the process of using SWIG with Microsoft Visual C++ 6 although the procedure may be similar with other compilers. In order for everything to work, you will need to have a JDK installed on your machine in order to read the JNI header files. 21.2.8.1 Running SWIG from Visual StudioIf you are developing your application within Microsoft Visual studio, SWIG can be invoked as a custom build option. The Examples\java directory has a few Windows Examples containing Visual Studio project (.dsp) files. The process to re-create the project files for a C project are roughly:
Note: If using C++, choose a C++ suffix for the wrapper file, for example Now, assuming all went well, SWIG will be automatically invoked when you build your project. When doing a build, any changes made to the interface file will result in SWIG being automatically invoked to produce a new version of the wrapper file. The Java classes that SWIG output should also be compiled into .class files. To run the native code in the DLL (example.dll), make sure that it is in your path then run your Java program which uses it, as described in the previous section. If the library fails to load have a look at Dynamic linking problems . 21.2.8.2 Using NMAKEAlternatively, a Makefile for use by NMAKE can be written. 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 : # Makefile for using SWIG and Java for C code 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 JAVA_INCLUDE = -ID:\jdk1.3\include -ID:\jdk1.3\include\win32 java:: swig -java -o $(WRAPFILE) $(INTERFACE) $(CC) $(CFLAGS) $(JAVA_INCLUDE) $(SRCS) $(WRAPFILE) set LIB=$(TOOLS)\lib $(LINK) $(LOPT) -out:example.dll $(LIBS) example.obj example_wrap.obj javac *.java
To build the DLL and compile the java code, run NMAKE (you may need to run 21.3 A tour of basic C/C++ wrappingBy default, SWIG attempts to build a natural Java interface to your C/C++ code. Functions are wrapped as functions, classes are wrapped as classes, variables are wrapped with JavaBean type getters and setters and so forth. This section briefly covers the essential aspects of this wrapping. 21.3.1 Modules, packages and generated Java classes
The SWIG
The JNI (C/C++) code is generated into a file which also contains the module name, for example
The generated Java classes can be placed into a Java package by using the swig -java -package com.bloggs.swig -outdir com/bloggs/swig example.i SWIG won't create the directory, so make sure it exists beforehand. 21.3.2 FunctionsThere is no such thing as a global Java function so global C functions are wrapped as static methods in the module class. For example, %module example int fact(int n); creates a static function that works exactly like you think it might: public class example { public static int fact(int n) { // makes call using JNI to the C function } }
The Java class System.out.println(example.fact(4)); 21.3.3 Global variablesC/C++ global variables are fully supported by SWIG. Java does not allow the overriding of the dot operator so all variables are accessed through getters and setters. Again because there is no such thing as a Java global variable, access to C/C++ global variables is done through static getter and setter functions in the module class. // SWIG interface file with global variables %module example ... %inline %{ extern int My_variable; extern double density; %} ... Now in Java : // Print out value of a C global variable System.out.println("My_variable = " + example.getMy_variable()); // Set the value of a C global variable example.setDensity(0.8442); The value returned by the getter will always be up to date even if the value is changed in C. Note that the getters and setters produced follow the JavaBean property design pattern. That is the first letter of the variable name is capitalized and preceded with set or get. If you have the misfortune of wrapping two variables that differ only in the capitalization of their first letters, use %rename to change one of the variable names. For example: %rename Clash RenamedClash; float Clash; int clash;
If a variable is declared as
To make ordinary variables read-only, you can use the %{ extern char *path; %} %immutable; extern char *path; %mutable;
The If you just want to make a specific variable immutable, supply a declaration name. For example: %{ extern char *path; %} %immutable path; ... extern char *path; // Read-only (due to %immutable) 21.3.4 Constants
C/C++ constants are wrapped as Java static final variables. To create a constant, use #define PI 3.14159 #define VERSION "1.0" %constant int FOO = 42; %constant const char *path = "/usr/local"; By default the generated static final variables are initialized by making a JNI call to get their value. The constants are generated into the constants interface and look like this: public interface exampleConstants { public final static double PI = exampleJNI.PI_get(); public final static String VERSION = exampleJNI.VERSION_get(); public final static int FOO = exampleJNI.FOO_get(); public final static String path = exampleJNI.path_get(); }
Note that SWIG has inferred the C type and used an appropriate Java type that will fit the range of all possible values for the C type. By default SWIG generates runtime constants. They are not compiler constants that can, for example, be used in a switch statement. This can be changed by using the %javaconst(1); %javaconst(0) BIG; %javaconst(0) LARGE; #define EXPRESSION (0x100+5) #define BIG 1000LL #define LARGE 2000ULL generates: public interface exampleConstants { public final static int EXPRESSION = (0x100+5); public final static long BIG = exampleJNI.BIG_get(); public final static java.math.BigInteger LARGE = exampleJNI.LARGE_get(); }
Note that SWIG has inferred the C
Be careful using the
There is an alternative directive which can be used for these rare constant values that won't compile as Java code. This is the %javaconst(1); %javaconstvalue("new java.math.BigInteger(\"2000\")") LARGE; %javaconstvalue(1000) BIG; #define EXPRESSION (0x100+5) #define BIG 1000LL #define LARGE 2000ULL
Note the string quotes for public interface exampleConstants { public final static int EXPRESSION = (0x100+5); public final static long BIG = 1000; public final static java.math.BigInteger LARGE = new java.math.BigInteger("2000"); }
Note: declarations declared as struct Maths { static const int FIVE = 5; }; Compatibility Note: In SWIG-1.3.19 and earlier releases, the constants were generated into the module class and the constants interface didn't exist. Backwards compatibility is maintained as the module class implements the constants interface (even though some consider this type of interface implementation to be bad practice): public class example implements exampleConstants { }
You thus have the choice of accessing these constants from either the module class or the constants interface, for example, 21.3.5 EnumerationsSWIG handles both named and unnamed (anonymous) enumerations. There is a choice of approaches to wrapping named C/C++ enums. This is due to historical reasons as SWIG's initial support for enums was limited and Java did not originally have support for enums. Each approach has advantages and disadvantages and it is important for the user to decide which is the most appropriate solution. There are four approaches of which the first is the default approach based on the so called Java typesafe enum pattern. The second generates proper Java enums. The final two approaches use simple integers for each enum item. Before looking at the various approaches for wrapping named C/C++ enums, anonymous enums are considered. 21.3.5.1 Anonymous enumsThere is no name for anonymous enums and so they are handled like constants. For example: enum { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; is wrapped into the constants interface, in a similar manner as constants (see previous section): public interface exampleConstants { public final static int ALE = exampleJNI.ALE_get(); public final static int LAGER = exampleJNI.LAGER_get(); public final static int STOUT = exampleJNI.STOUT_get(); public final static int PILSNER = exampleJNI.PILSNER_get(); public final static int PILZ = exampleJNI.PILZ_get(); }
The %javaconst(1); %javaconst(0) PILSNER; enum { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; generates: public interface exampleConstants { public final static int ALE = 0; public final static int LAGER = 10; public final static int STOUT = LAGER + 1; public final static int PILSNER = exampleJNI.PILSNER_get(); public final static int PILZ = PILSNER; }
As in the case of constants, you can access them through either the module class or the constants interface, for example, 21.3.5.2 Typesafe enumsThis is the default approach to wrapping named enums. The typesafe enum pattern is a relatively well known construct to work around the lack of enums in versions of Java prior to JDK 1.5. It basically defines a class for the enumeration and permits a limited number of final static instances of the class. Each instance equates to an enum item within the enumeration. The implementation is in the “enumtypesafe.swg” file. Let's look at an example: %include "enumtypesafe.swg" // optional as typesafe enums are the default enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; will generate: public final class Beverage { public final static Beverage ALE = new Beverage("ALE"); public final static Beverage LAGER = new Beverage("LAGER", exampleJNI.LAGER_get()); public final static Beverage STOUT = new Beverage("STOUT"); public final static Beverage PILSNER = new Beverage("PILSNER"); public final static Beverage PILZ = new Beverage("PILZ", exampleJNI.PILZ_get()); [... additional support methods omitted for brevity ...] }
See Typesafe enum classes to see the omitted support methods. Note that the enum item with an initializer (LAGER) is initialized with the enum value obtained via a JNI call. However, as with anonymous enums and constants, use of the %include "enumtypesafe.swg" // optional as typesafe enums are the default %javaconst(1); enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; will generate: public final class Beverage { public final static Beverage ALE = new Beverage("ALE"); public final static Beverage LAGER = new Beverage("LAGER", 10); public final static Beverage STOUT = new Beverage("STOUT"); public final static Beverage PILSNER = new Beverage("PILSNER"); public final static Beverage PILZ = new Beverage("PILZ", PILSNER); [... additional support methods omitted for brevity ...] }
The generated code is easier to read and more efficient as a true constant is used instead of a JNI call. As is the case for constants, the default is Typesafe enums have their advantages over using plain integers in that they they can be used in a typesafe manner. However, there are limitations. For example, they cannot be used in switch statements and serialization is an issue. Please look at the following references for further information: Replace Enums with Classes in Effective Java Programming on the Sun website, Create enumerated constants in Java JavaWorld article, Java Tip 133: More on typesafe enums and Java Tip 122: Beware of Java typesafe enumerations JavaWorld tips. Note that the syntax required for using typesafe enums is the same as that for proper Java enums. This is useful during the period that a project has to support legacy versions of Java. When upgrading to JDK 1.5 or later, proper Java enums could be used instead, without users having to change their code. The following section details proper Java enum generation. 21.3.5.3 Proper Java enumsProper Java enums were only introduced in JDK 1.5 so this approach is only compatible with more recent versions of Java. Java enums have been designed to overcome all the limitations of both typesafe and type unsafe enums and should be the choice solution, provided older versions of Java do not have to be supported. In this approach, each named C/C++ enum is wrapped by a Java enum. Java enums, by default, do not support enums with initializers. Java enums are in many respects similar to Java classes in that they can be customised with additional methods. SWIG takes advantage of this feature to facilitate wrapping C/C++ enums that have initializers. In order to wrap all possible C/C++ enums using proper Java enums, the “enums.swg” file must be used. Let's take a look at an example. %include "enums.swg" %javaconst(1); enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; will generate: public enum Beverage { ALE, LAGER(10), STOUT, PILSNER, PILZ(PILSNER); [... additional support methods omitted for brevity ...] }
See Proper Java enum classes to see the omitted support methods. The generated Java enum has numerous additional methods to support enums with initializers, such as The additional support methods need not be generated if none of the enum items have initializers and this is covered later in the Simpler Java enums for enums without initializers section. 21.3.5.4 Type unsafe enumsIn this approach each enum item in a named enumeration is wrapped as a static final integer in a class named after the C/C++ enum name. This is a commonly used pattern in Java to simulate C/C++ enums, but it is not typesafe. However, the main advantage over the typesafe enum pattern is enum items can be used in switch statements. In order to use this approach, the “enumtypeunsafe.swg” file must be used. Let's take a look at an example. %include "enumtypeunsafe.swg" %javaconst(1); enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; will generate: public final class Beverage { public final static int ALE = 0; public final static int LAGER = 10; public final static int STOUT = LAGER + 1; public final static int PILSNER = STOUT + 1; public final static int PILZ = PILSNER; }
As is the case previously, the default is Note that unlike typesafe enums, this approach requires users to mostly use different syntax compared with proper Java enums. Thus the upgrade path to proper enums provided in JDK 1.5 is more painful. 21.3.5.5 Simple enumsThis approach is similar to the type unsafe approach. Each enum item is also wrapped as a static final integer. However, these integers are not generated into a class named after the C/C++ enum. Instead, global enums are generated into the constants interface. Also, enums defined in a C++ class have their enum items generated directly into the Java proxy class rather than an inner class within the Java proxy class. In fact, this approach is effectively wrapping the enums as if they were anonymous enums and the resulting code is as per anonymous enums. The implementation is in the “enumsimple.swg” file. Compatibility Note: SWIG-1.3.21 and earlier versions wrapped all enums using this approach. The type unsafe approach is preferable to this one and this simple approach is only included for backwards compatibility with these earlier versions of SWIG. 21.3.6 PointersC/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Here is a rather simple interface: %module example FILE *fopen(const char *filename, const char *mode); int fputs(const char *, FILE *); int fclose(FILE *); When wrapped, you will be able to use the functions in a natural way from Java. For example: SWIGTYPE_p_FILE f = example.fopen("junk","w"); example.fputs("Hello World\n", f); example.fclose(f);
C pointers in the Java module are stored in a Java Once obtained, a type wrapper object can be freely passed around to different C functions that expect to receive an object of that type. The only thing you can't do is dereference the pointer from Java. Of course, that isn't much of a concern in this example. As much as you might be inclined to modify a pointer value directly from Java, don't. The value is not necessarily the same as the logical memory address of the underlying object. The value will vary depending on the native byte-ordering of the platform (i.e., big-endian vs. little-endian). Most JVMs are 32 bit applications so any JNI code must also be compiled as 32 bit. The net result is pointers in JNI code are also 32 bits and are stored in the high order 4 bytes on big-endian machines and in the low order 4 bytes on little-endian machines. By design it is also not possible to manually cast a pointer to a new type by using Java casts as it is particularly dangerous especially when casting C++ objects. If you need to cast a pointer or change its value, consider writing some helper functions instead. For example: %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; } %} 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 a NULL pointer if the conversion can't be performed. 21.3.7 StructuresIf you wrap a C structure, it is wrapped by a Java class with getters and setters for access to the member variables. For example, struct Vector { double x,y,z; }; is used as follows: Vector v = new Vector(); v.setX(3.5); v.setY(7.2); double x = v.getX(); double y = v.getY(); The variable setters and getters are also based on the JavaBean design pattern already covered under the Global variables section. Similar access is provided for unions and the public data members of C++ classes. This object is actually an instance of a Java class that has been wrapped around a pointer to the C structure. This instance doesn't actually do anything–it just serves as a proxy. The pointer to the C object is held in the Java proxy class in much the same way as pointers are held by type wrapper classes. Further details about Java proxy classes are covered a little later.
struct Foo { ... %immutable; int x; /* Read-only members */ char *name; %mutable; ... };
When If a structure contains arrays, access to those arrays is managed through pointers. For example, consider this: struct Bar { int x[16]; }; If accessed in Java, you will see behavior like this: Bar b = new Bar(); SWIGTYPE_p_int x = b.getX();
This pointer can be passed around to functions that expect to receive an Bar b = new Bar(); SWIGTYPE_p_int x = b.getX(); Bar c = new Bar(); c.setX(x); // Copy contents of b.x to c.x
For array assignment (setters not getters), SWIG copies the entire contents of the array starting with the data pointed to by 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: struct Foo { int a; }; struct Bar { Foo f; };
Now, suppose that you access the Bar b = new Bar(); Foo x = b.getF();
In this case, Bar b; Foo *x = &b->f; /* Points inside b */ Because the pointer points inside the structure, you can modify the contents and everything works just like you would expect. For example: Bar b = new Bar(); b.getF().setA(3); // Modify b.f.a Foo x = b.getF(); x.setA(3); // Modify x.a - this is the same as b.f.a 21.3.8 C++ classesC++ classes are wrapped by Java classes as well. For example, if you have this class, class List { public: List(); ~List(); int search(char *item); void insert(char *item); void remove(char *item); char *get(int n); int length; }; you can use it in Java like this: List l = new List(); l.insert("Ale"); l.insert("Stout"); l.insert("Lager"); String item = l.get(2); int length = l.getLength(); Class data members are accessed in the same manner as C structures. Static class members are unsurprisingly wrapped as static members of the Java class: class Spam { public: static void foo(); static int bar; }; The static members work like any other Java static member: Spam.foo(); int bar = Spam.getBar(); 21.3.9 C++ inheritanceSWIG is fully aware of issues related to C++ inheritance. Therefore, if you have classes like this class Foo { ... }; class Bar : public Foo { ... }; those classes are wrapped into a hierarchy of Java classes that reflect the same inheritance structure: Bar b = new Bar(); Class c = b.getClass(); System.out.println(c.getSuperclass().getName()); will of course display: Foo Furthermore, if you have functions like this void spam(Foo *f);
then the Java function Note that Java does not support multiple inheritance so any multiple inheritance in the C++ code is not going to work. A warning is given when multiple inheritance is detected and only the first base class is used. 21.3.10 Pointers, references, arrays and pass by valueIn C++, there are many different ways a function might receive and manipulate objects. For example: 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 In Java, there is no detailed distinction like this–specifically, there are only instances of classes. There are no pointers nor references. 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 from Java: Foo f = new Foo(); // Create a Foo example.spam1(f); // Ok. Pointer example.spam2(f); // Ok. Reference example.spam3(f); // Ok. Value. example.spam4(f); // Ok. Array (1 element) Similar behavior occurs for return values. For example, if you had functions like this, Foo *spam5(); Foo &spam6(); Foo spam7();
then all three functions will return a pointer to some 21.3.10.1 Null pointers
Working with null pointers is easy. A Java example.spam1(null); // Pointer - ok example.spam2(null); // Reference - NullPointerException example.spam3(null); // Value - NullPointerException example.spam4(null); // Array - ok
For 21.3.11 C++ overloaded functionsC++ overloaded functions, methods, and constructors are mostly supported by SWIG. For example, if you have two functions like this: %module example void foo(int); void foo(char *c); You can use them in Java in a straightforward manner: example.foo(3); // foo(int) example.foo("Hello"); // foo(char *c) Similarly, if you have a class like this, class Foo { public: Foo(); Foo(const Foo &); ... }; you can write Java code like this: Foo f = new Foo(); // Create a Foo Foo g = new Foo(f); // Copy f Overloading support is not quite as flexible as in C++. Sometimes there are methods that SWIG cannot disambiguate as there can be more than one C++ type mapping onto a single Java type. For example: void spam(int); void spam(unsigned short); Here both int and unsigned short map onto a Java int. Here is another example: void foo(Bar *b); void foo(Bar &b); If declarations such as these appear, you will get a warning message like this: example.i:12: Warning(515): Overloaded method spam(unsigned short) ignored. Method spam(int) at example.i:11 used. To fix this, you either need to either rename or ignore one of the methods. For example: %rename(spam_ushort) spam(unsigned short); ... void spam(int); void spam(unsigned short); // Now renamed to spam_ushort or %ignore spam(unsigned short); ... void spam(int); void spam(unsigned short); // Ignored 21.3.12 C++ default argumentsAny function with a default argument is wrapped by generating an additional function for each argument that is defaulted. For example, if we have the following C++: %module example void defaults(double d=10.0, int i=0); The following methods are generated in the Java module class: public class example { public static void defaults(double d, int i) { ... } public static void defaults(double d) { ... } public static void defaults() { ... } } It is as if SWIG had parsed three separate overloaded methods. The same approach is taken for static methods, constructors and member methods. Compatibility note: Versions of SWIG prior to SWIG-1.3.23 wrapped these with a single wrapper method and so the default values could not be taken advantage of from Java. Further details on default arguments and how to restore this approach are given in the more general Default arguments section. 21.3.13 C++ namespacesSWIG 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, %module example namespace foo { int fact(int n); struct Vector { double x,y,z; }; }; it works in Java as follows: int f = example.fact(3); Vector v = new Vector(); v.setX(3.4); double y = v.getY();
If your program has more than one namespace, name conflicts (if any) can be resolved using %rename(Bar_spam) Bar::spam; namespace Foo { int spam(); } namespace Bar { int spam(); } If you have more than one namespace and you want to keep their symbols separate, consider wrapping them as separate SWIG modules. Each SWIG module can be placed into a separate package. 21.3.14 C++ templates
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 %module example %{ #include <utility> %} 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>; In Java: pairii p = new pairii(3,4); int first = p.getFirst(); int second = p.getSecond(); Obviously, there is more to template wrapping than shown in this example. More details can be found in the SWIG and C++ chapter. 21.3.15 C++ Smart Pointers
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 template<class T> class SmartPtr { ... T *operator->(); ... } Then, if you have a class like this, class Foo { public: int x; int bar(); }; A smart pointer would be used in C++ as follows: SmartPtr<Foo> p = CreateFoo(); // Created somehow (not shown) ... p->x = 3; // Foo::x int y = p->bar(); // Foo::bar
To wrap this in Java, simply tell SWIG about the %module example ... %template(SmartPtrFoo) SmartPtr<Foo>; ... Now, in Java, everything should just “work”: SmartPtrFoo p = example.CreateFoo(); // Create a smart-pointer somehow p.setX(3); // Foo::x int y = p.bar(); // Foo::bar
If you ever need to access the underlying pointer returned by Foo f = p.__deref__(); // Returns underlying Foo * 21.4 Further details on the generated Java classesIn the previous section, a high-level view of Java wrapping was presented. A key component of this wrapping is that structures and classes are wrapped by Java proxy classes and type wrapper classes are used in situations where no proxies are generated. This provides a very natural, type safe Java interface to the C/C++ code and fits in with the Java programming paradigm. However, a number of low-level details were omitted. This section provides a brief overview of how the proxy classes work and then covers the type wrapper classes. Finally enum classes are covered. First, the crucial intermediary JNI class is considered. 21.4.1 The intermediary JNI classIn the "SWIG basics" and "SWIG and C++" chapters, details of low-level structure and class wrapping are described. To summarize those chapters, if you have a global function and class like this class Foo { public: int x; int spam(int num, Foo* foo); }; void egg(Foo* chips); then SWIG transforms the class into a set of low-level procedural wrappers. These procedural wrappers essentially perform the equivalent of this C++ code: 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 num, Foo* foo) { return f->spam(num, foo); } These procedural function names don't actually exist, but their functionality appears inside the generated JNI functions. The JNI functions have to follow a particular naming convention so the function names are actually: SWIGEXPORT jlong JNICALL Java_exampleJNI_new_1Foo(JNIEnv *jenv, jclass jcls); SWIGEXPORT void JNICALL Java_exampleJNI_delete_1Foo(JNIEnv *jenv, jclass jcls, jlong jarg1); SWIGEXPORT void JNICALL Java_exampleJNI_Foo_1x_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2); SWIGEXPORT jint JNICALL Java_exampleJNI_Foo_1x_1get(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_); SWIGEXPORT jint JNICALL Java_exampleJNI_Foo_1spam(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jlong jarg3, jobject jarg3_); SWIGEXPORT void JNICALL Java_exampleJNI_egg(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_); For every JNI C function there has to be a static native Java function. These appear in the intermediary JNI class: class exampleJNI { public final static native long new_Foo(); public final static native void delete_Foo(long jarg1); public final static native void Foo_x_set(long jarg1, Foo jarg1_, int jarg2); public final static native int Foo_x_get(long jarg1, Foo jarg1_); public final static native int Foo_spam(long jarg1, Foo jarg1_, int jarg2, long jarg3, Foo jarg3_); public final static native void egg(long jarg1, Foo jarg1_); } This class contains the complete Java - C/C++ interface so all function calls go via this class. As this class acts as a go-between for all JNI calls to C/C++ code from the Java proxy classes, type wrapper classes and module class, it is known as the intermediary JNI class.
You may notice that SWIG uses a Java long wherever a pointer or class object needs to be marshalled across the Java-C/C++ boundary. This approach leads to minimal JNI code which makes for better performance as JNI code involves a lot of string manipulation. SWIG favours generating Java code over JNI code as Java code is compiled into byte code and avoids the costly string operations needed in JNI code. This approach has a downside though as the proxy class might get collected before the native method has completed. You might notice above that there is an additional parameters with a underscore postfix, eg The functions in the intermediary JNI class cannot be accessed outside of its package. Access to them is gained through the module class for globals otherwise the appropriate proxy class.
The name of the intermediary JNI class can be changed from its default, that is, the module name with JNI appended after it. The module directive attribute %module (jniclassname="name") modulename
If 21.4.1.1 The intermediary JNI class pragmasThe intermediary JNI class can be tailored through the use of pragmas, but is not commonly done. The pragmas for this class are:
The pragma code appears in the generated intermediary JNI class where you would expect: [ jniclassimports pragma ] [ jniclassclassmodifiers pragma ] jniclassname extends [ jniclassbase pragma ] implements [ jniclassinterfaces pragma ] { [ jniclasscode pragma ] ... SWIG generated native methods ... }
The %pragma(java) jniclasscode=%{ static { try { System.loadLibrary("example"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. \n" + e); System.exit(1); } } %}
Pragmas will take either %pragma(java) jniclassclassmodifiers="public class" All the methods in the intermediary JNI class will then be callable outside of the package as the method modifiers are public by default. 21.4.2 The Java module classAll global functions and variable getters/setters appear in the module class. For our example, there is just one function: public class example { public static void egg(Foo chips) { exampleJNI.egg(Foo.getCPtr(chips), chips); } } The module class is necessary as there is no such thing as a global in Java so all the C globals are put into this class. They are generated as static functions and so must be accessed as such by using the module name in the static function call: example.egg(new Foo());
The primary reason for having the module class wrapping the calls in the intermediary JNI class is to implement static type checking. In this case only a 21.4.2.1 The Java module class pragmasThe module class can be tailored through the use of pragmas, in the same manner as the intermediary JNI class. The pragmas are similarly named and are used in the same way. The complete list follows:
The pragma code appears in the generated module class like this: [ moduleimports pragma ] [ modulemodifiers pragma ] modulename extends [ modulebase pragma ] implements [ moduleinterfaces pragma ] { [ modulecode pragma ] ... SWIG generated wrapper functions ... } See The intermediary JNI class pragmas section for further details on using pragmas. 21.4.3 Java proxy classesA Java proxy class is generated for each structure, union or C++ class that is wrapped. Proxy classes have also been called peer classes. The default proxy class for our previous example looks like this: public class Foo { private long swigCPtr; protected boolean swigCMemOwn; protected Foo(long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; } protected static long getCPtr(Foo obj) { return (obj == null) ? 0 : obj.swigCPtr; } protected void finalize() { delete(); } public synchronized void delete() { if(swigCPtr != 0 && swigCMemOwn) { swigCMemOwn = false; exampleJNI.delete_Foo(swigCPtr); } swigCPtr = 0; } public void setX(int value) { exampleJNI.Foo_x_set(swigCPtr, this, value); } public int getX() { return exampleJNI.Foo_x_get(swigCPtr, this); } public int spam(int num, Foo foo) { return exampleJNI.Foo_spam(swigCPtr, this, num, Foo.getCPtr(foo), foo); } public Foo() { this(exampleJNI.new_Foo(), true); } }
This class merely holds a pointer to the underlying C++ object ( Foo f = new Foo(); f.setX(3); int y = f.spam(5, new Foo()); 21.4.3.1 Memory management
Each proxy class has an ownership flag When an object is created by a constructor or returned by value, Java automatically takes ownership of the result. On the other hand, when pointers or references are returned to Java, there is often no way to know where they came from. Therefore, the ownership is set to false. For example: class Foo { public: Foo(); Foo bar1(); Foo &bar2(); Foo *bar2(); }; In Java: Foo f = new Foo(); // f.swigCMemOwn = true Foo f1 = f.bar1(); // f1.swigCMemOwn = true Foo f2 = f.bar2(); // f2.swigCMemOwn = false Foo f3 = f.bar3(); // f3.swigCMemOwn = false This behavior for pointers and references 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 Java to assume ownership and destroy it! For the most part, memory management issues remain hidden. However, there are situations where you might have to manually change the ownership of an object. For instance, consider code like this: class Obj {}; class Node { Obj *value; public: void set_value(Obj *v) { value = v; } }; Now, consider the following Java code: Node n = new Node(); // Create a node { Obj o = new Obj(); // Create an object n.set_value(o); // Set value } // o goes out of scope
In this case, the Node
To work around this, the ownership flag of
Sometimes a function will create memory and return a pointer to a newly allocated object. SWIG has no way of knowing this so by default the proxy class does not manage the returned object. However, you can tell the proxy class to manage the memory if you specify the class Obj {...}; class Factory { public: static Obj *createObj() { return new Obj(); } }; If we call the factory function, then we have to manually delete the memory: Obj obj = Factory.createObj(); // obj.swigCMemOwn = false ... obj.delete(); Now add in the %newobject directive: %newobject Factory::createObj(); class Obj {...}; class Factory { public: static Obj *createObj() { return new Obj(); } };
A call to Obj obj = Factory.createObj(); // obj.swigCMemOwn = true; ... Some memory management issues are quite tricky to fix and may only be noticeable after using for a long time. One such issue is premature garbage collection of an object created from Java and resultant usage from C++ code. The section on typemap examples cover two such scenarios, Memory management for objects passed to the C++ layer and Memory management when returning references to member variables 21.4.3.2 Inheritance
Java proxy classes will mirror C++ inheritance chains. For example, given the base class class Base { public: virtual double foo(); }; class Derived : public Base { public: virtual double foo(); }; The base class is generated much like any other proxy class seen so far: public class Base { private long swigCPtr; protected boolean swigCMemOwn; protected Base(long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; } protected static long getCPtr(Base obj) { return (obj == null) ? 0 : obj.swigCPtr; } protected void finalize() { delete(); } public synchronized void delete() { if(swigCPtr != 0 && swigCMemOwn) { swigCMemOwn = false; exampleJNI.delete_Base(swigCPtr); } swigCPtr = 0; } public double foo() { return exampleJNI.Base_foo(swigCPtr, this); } public Base() { this(exampleJNI.new_Base(), true); } }
The public class Derived extends Base { private long swigCPtr; protected Derived(long cPtr, boolean cMemoryOwn) { super(exampleJNI.SWIGDerivedUpcast(cPtr), cMemoryOwn); swigCPtr = cPtr; } protected static long getCPtr(Derived obj) { return (obj == null) ? 0 : obj.swigCPtr; } protected void finalize() { delete(); } public synchronized void delete() { if(swigCPtr != 0 && swigCMemOwn) { swigCMemOwn = false; exampleJNI.delete_Derived(swigCPtr); } swigCPtr = 0; super.delete(); } public double foo() { return exampleJNI.Derived_foo(swigCPtr, this); } public Derived() { this(exampleJNI.new_Derived(), true); } }
Note the memory ownership is controlled by the base class. However each class in the inheritance hierarchy has its own pointer value which is obtained during construction. The
It is of course possible to extend 21.4.3.3 Proxy classes and garbage collection
By default each proxy class has a
If the Some not so ideal solutions are:
Runtime.getRuntime().addShutdownHook( new Thread() { public void run() { System.gc(); System.runFinalization(); } } ); }
Although this usually works, the documentation doesn't guarantee that
// use myA …
myA.delete();
// any use of myA here would crash the JVM
myA=null;
// any use of myA here would cause a Java null pointer exception to be thrown
The SWIG generated code ensures that the memory is not deleted twice, in the event the finalizers get called in addition to the manual
See the How to Handle Java Finalization's Memory-Retention Issues article for alternative approaches to managing memory by avoiding finalizers altogether. 21.4.3.4 The premature garbage collection prevention parameter for proxy class marshallingAs covered earlier, the C/C++ struct/class pointer is stored in the proxy class as a Java long and when needed is passed into the native method where it is cast into the appropriate type. This approach provides very fast marshalling but could be susceptible to premature garbage collection. Consider the following C++ code: class Wibble { }; void wobble(Wibble &w);
The module class contains the Java wrapper for the global public class example { ... public static void wobble(Wibble w) { exampleJNI.wobble(Wibble.getCPtr(w), w); } }
where public class exampleJNI { ... public final static native void wobble(long jarg1, Wibble jarg1_); }
The second parameter, public class exampleJNI { ... public final static native void wobble(long jarg1); }
and the following simple call to { Wibble w = new Wibble(); example.wobble(w); } The hotspot compiler effectively sees something like: { Wibble w = new Wibble(); long w_ptr = Wibble.getCPtr(w); // w is no longer reachable exampleJNI.wobble(w_ptr); }
The { Wibble w = new Wibble(); long w_ptr = Wibble.getCPtr(w); exampleJNI.wobble(w_ptr, w); // w is no longer reachable } and therefore there is no possibility of premature garbage collection. In practice, this premature garbage collection was only ever observed in Sun's server JVM from jdk-1.3 onwards and in Sun's client JVM from jdk-1.6 onwards.
The premature garbage collection prevention parameter for proxy classes is generated by default whenever proxy classes are passed by value, reference or with a pointer. The implementation for this extra parameter generation requires the “jtype” typemap to contain
The additional parameter does impose a slight performance overhead and the parameter generation can be suppressed globally with the %typemap(jtype, nopgcpp="1") Wibble & "long" Compatibility note: The generation of this additional parameter did not occur in versions prior to SWIG-1.3.30. 21.4.3.5 Single threaded applications and thread safetySingle threaded Java applications using JNI need to consider thread safety. The same applies for the C# module where the .NET wrappers use PInvoke. Consider the C++ class: class Test { string str; public: Test() : str("initial") {} }; and the Java proxy class generated by SWIG: public class Test { private long swigCPtr; protected boolean swigCMemOwn; protected Test(long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; } protected static long getCPtr(Test obj) { return (obj == null) ? 0 : obj.swigCPtr; } protected void finalize() { delete(); } // Call C++ destructor public synchronized void delete() { if(swigCPtr != 0 && swigCMemOwn) { swigCMemOwn = false; exampleJNI.delete_Test(swigCPtr); } swigCPtr = 0; } // Call C++ constructor public Test() { this(exampleJNI.new_Test(), true); } }
It has two methods that call JNI methods, namely, Note that some of the STL in Visual C++ 6 is not thread safe, so although code might be linked to the multithread runtime libraries, undefined behaviour might still occur in a single threaded Java program. Similarly some older versions of Sun Studio have bugs in the multi-threaded implementation of the std::string class and so will lead to undefined behaviour in these supposedly single threaded Java applications. The following innocuous Java usage of Test is an example that will crash very quickly on a multiprocessor machine if the JNI compiled code is linked against the single thread C runtime libraries. for (int i=0; i<100000; i++) { System.out.println("Iteration " + i); for (int k=0; k<10; k++) { Test test = new Test(); } System.gc(); } 21.4.4 Type wrapper classes
The generated type wrapper class, for say an public class SWIGTYPE_p_int { private long swigCPtr; protected SWIGTYPE_p_int(long cPtr, boolean bFutureUse) { swigCPtr = cPtr; } protected SWIGTYPE_p_int() { swigCPtr = 0; } protected static long getCPtr(SWIGTYPE_p_int obj) { return obj.swigCPtr; } } The methods do not have public access, so by default it is impossible to do anything with objects of this class other than pass them around. The methods in the class are part of the inner workings of SWIG. If you need to mess around with pointers you will have to use some typemaps specific to the Java module to achieve this. The section on Java typemaps details how to modify the generated code. Note that if you use a pointer or reference to a proxy class in a function then no type wrapper class is generated because the proxy class can be used as the function parameter. If however, you need anything more complicated like a pointer to a pointer to a proxy class then a typewrapper class is generated for your use.
Note that SWIG generates a type wrapper class and not a proxy class when it has not parsed the definition of a type that gets used. For example, say SWIG has not parsed the definition of void spam(Snazzy *x, Snazzy &y, Snazzy z);
Should SWIG not know anything about public static void spam(SWIGTYPE_p_Snazzy x, SWIGTYPE_p_Snazzy y, SWIGTYPE_p_Snazzy z) { ... }
Note that typedefs are tracked by SWIG and the typedef name is used to construct the type wrapper class name. For example, consider the case where typedef int Snazzy; void spam(Snazzy *x, Snazzy &y, Snazzy z); Because the typedefs have been tracked the Java function generated is: public static void spam(SWIGTYPE_p_int x, SWIGTYPE_p_int y, int z) { ... } 21.4.5 Enum classesSWIG can generate three types of enum classes. The Enumerations section discussed these but omitted all the details. The following sub-sections detail the various types of enum classes that can be generated. 21.4.5.1 Typesafe enum classesThe following example demonstrates the typesafe enum classes which SWIG generates: %include "enumtypesafe.swg" %javaconst(1); enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; The following is the code that SWIG generates: public final class Beverage { public final static Beverage ALE = new Beverage("ALE"); public final static Beverage LAGER = new Beverage("LAGER", 10); public final static Beverage STOUT = new Beverage("STOUT"); public final static Beverage PILSNER = new Beverage("PILSNER"); public final static Beverage PILZ = new Beverage("PILZ", PILSNER); public final int swigValue() { return swigValue; } public String toString() { return swigName; } public static Beverage swigToEnum(int swigValue) { if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue) return swigValues[swigValue]; for (int i = 0; i < swigValues.length; i++) if (swigValues[i].swigValue == swigValue) return swigValues[i]; throw new IllegalArgumentException("No enum " + Beverage.class + " with value " + swigValue); } private Beverage(String swigName) { this.swigName = swigName; this.swigValue = swigNext++; } private Beverage(String swigName, int swigValue) { this.swigName = swigName; this.swigValue = swigValue; swigNext = swigValue+1; } private Beverage(String swigName, Beverage swigEnum) { this.swigName = swigName; this.swigValue = swigEnum.swigValue; swigNext = this.swigValue+1; } private static Beverage[] swigValues = { ALE, LAGER, STOUT, PILSNER, PILZ }; private static int swigNext = 0; private final int swigValue; private final String swigName; }
As can be seen, there are a fair number of support methods for the typesafe enum pattern. The typesafe enum pattern involves creating a fixed number of static instances of the enum class. The constructors are private to enforce this. Three constructors are available - two for C/C++ enums with an initializer and one for those without an initializer. Note that the two enums with initializers, 21.4.5.2 Proper Java enum classesThe following example demonstrates the Java enums approach: %include "enums.swg" %javaconst(1); enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; SWIG will generate the following Java enum: public enum Beverage { ALE, LAGER(10), STOUT, PILSNER, PILZ(PILSNER); public final int swigValue() { return swigValue; } public static Beverage swigToEnum(int swigValue) { Beverage[] swigValues = Beverage.class.getEnumConstants(); if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue) return swigValues[swigValue]; for (Beverage swigEnum : swigValues) if (swigEnum.swigValue == swigValue) return swigEnum; throw new IllegalArgumentException("No enum " + Beverage.class + " with value " + swigValue); } private Beverage() { this.swigValue = SwigNext.next++; } private Beverage(int swigValue) { this.swigValue = swigValue; SwigNext.next = swigValue+1; } private Beverage(Beverage swigEnum) { this.swigValue = swigEnum.swigValue; SwigNext.next = this.swigValue+1; } private final int swigValue; private static class SwigNext { private static int next = 0; } }
The enum items appear first. Like the typesafe enum pattern, the constructors are private. The constructors are required to handle C/C++ enums with initializers. The 21.4.5.3 Type unsafe enum classesThe following example demonstrates type unsafe enums: %include "enumtypeunsafe.swg" %javaconst(1); enum Beverage { ALE, LAGER=10, STOUT, PILSNER, PILZ=PILSNER }; SWIG will generate the following simple class: public final class Beverage { public final static int ALE = 0; public final static int LAGER = 10; public final static int STOUT = LAGER + 1; public final static int PILSNER = STOUT + 1; public final static int PILZ = PILSNER; } 21.5 Cross language polymorphism using directorsProxy classes provide a natural, object-oriented way to wrap C++ classes. as described earlier, each proxy instance has an associated C++ instance, and method calls from Java to the proxy are passed to the C++ instance transparently via C wrapper functions. This arrangement is asymmetric in the sense that no corresponding mechanism exists to pass method calls down the inheritance chain from C++ to Java. In particular, if a C++ class has been extended in Java (by deriving from the proxy class), these classes will not be visible from C++ code. Virtual method calls from C++ are thus not able to access the lowest implementation in the inheritance chain. SWIG can address this problem and make the relationship between C++ classes and proxy classes more symmetric. To achieve this goal, new classes called directors are introduced at the bottom of the C++ inheritance chain. The job of the directors is to route method calls correctly, either to C++ implementations higher in the inheritance chain or to Java implementations lower in the inheritance chain. The upshot is that C++ classes can be extended in Java and from C++ these extensions look exactly like native C++ classes. Neither C++ code nor Java code needs to know where a particular method is implemented: the combination of proxy classes, director classes, and C wrapper functions transparently takes care of all the cross-language method routing. 21.5.1 Enabling directorsThe director feature is disabled by default. To use directors you must make two changes to the interface file. First, add the “directors” option to the %module directive, like this: %module(directors="1") modulename Without this option no director code will be generated. Second, you must use the %feature(“director”) directive to tell SWIG which classes and methods should get directors. The %feature directive can be applied globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); // generate directors for all virtual methods in class Foo %feature("director") Foo; // generate a director for just Foo::bar() %feature("director") Foo::bar; You can use the %feature(“nodirector”) directive to turn off directors for specific classes or methods. So for example, %feature("director") Foo; %feature("nodirector") Foo::bar; will generate directors for all virtual methods of class Foo except bar(). Directors can also be generated implicitly through inheritance. In the following, class Bar will get a director class that handles the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: virtual void one(); virtual void two(); }; class Bar: public Foo { public: virtual void three(); }; 21.5.2 Director classes
For each class that has directors enabled, SWIG generates a new class that derives from both the class in question and a special
For simplicity let's ignore the In reality, the “appropriate place” is one of only two possibilities: C++ or Java. Once this decision is made, the rest is fairly easy. If the correct implementation is in C++, then the lowest implementation of the method in the C++ inheritance chain is called explicitly. If the correct implementation is in Java, the Java API is used to call the method of the underlying Java object (after which the usual virtual method resolution in Java automatically finds the right implementation). 21.5.3 Overhead and code bloatEnabling directors for a class will generate a new director method for every virtual method in the class' inheritance chain. This alone can generate a lot of code bloat for large hierarchies. Method arguments that require complex conversions to and from Java types can result in large director methods. For this reason it is recommended that directors are selectively enabled only for specific classes that are likely to be extended in Java and used in C++. Although directors make it natural to mix native C++ objects with Java objects (as director objects), one should be aware of the obvious fact that method calls to Java objects from C++ will be much slower than calls to C++ objects. Additionally, compared to classes that do not use directors, the call routing in the director methods adds a small overhead. This situation can be optimized by selectively enabling director methods (using the %feature directive) for only those methods that are likely to be extended in Java. 21.5.4 Simple directors exampleConsider the following SWIG interface file: %module(directors="1") example; %feature("director") DirectorBase; class DirectorBase { public: virtual ~DirectorBase() {} virtual void upcall_method() {} }; void callup(DirectorBase *director) { director->upcall_method(); }
The following public class DirectorDerived extends DirectorBase { public DirectorDerived() { } public void upcall_method() { System.out.println("DirectorDerived::upcall_method() invoked."); } } Running the following Java code DirectorDerived director = new DirectorDerived(); example.callup(director); will result in the following being output: DirectorDerived::upcall_method() invoked. 21.5.5 Director threading issues
Depending on your operating system and version of Java and how you are using threads, you might find the JVM hangs on exit. There are a couple of solutions to try out. The preferred solution requires jdk-1.4 and later and uses Macros can be defined on the commandline when compiling your C++ code, or alternatively added to the C++ wrapper file as shown below: %insert("runtime") %{ #define SWIG_JAVA_NO_DETACH_CURRENT_THREAD %} 21.6 Accessing protected membersWhen using directors, the protected virtual methods are also wrapped. These methods are wrapped with a protected Java proxy method, so the only way that Java code can access these is from within a Java class derived from the director class.
Members which are protected and non-virtual can also be accessed when using the 'allprotected' mode. The allprotected mode requires directors and is turned on by setting the %module(directors="1", allprotected="1") modulename Protected member variables and methods (both static and non-static) will then be wrapped with protected access in the Java proxy class. Note: Neither the directors option nor the allprotected mode support types defined with protected scope. This includes any enums or typedefs declared in the protected section of the C++ class. The following simple example is a class with numerous protected members, including the constructor and destructor: %module(directors="1", allprotected="1") example %feature("director") ProtectedBase; // Ignore use of unsupported types (those defined in the protected section) %ignore ProtectedBase::typedefs; %inline %{ class ProtectedBase { protected: ProtectedBase() {} virtual ~ProtectedBase() {} virtual void virtualMethod() const {} void nonStaticMethod(double d) const {} static void staticMethod(int i) {} int instanceMemberVariable; static int staticMemberVariable; // unsupported: types defined with protected access and the methods/variables which use them typedef int IntegerType; IntegerType typedefs(IntegerType it) { return it; } }; int ProtectedBase::staticMemberVariable = 10; %}
Note that the The proxy methods are protected, so the only way the protected members can be accessed is within a class that derives from the director class, such as the following: class MyProtectedBase extends ProtectedBase { public MyProtectedBase() { } public void accessProtected() { virtualMethod(); nonStaticMethod(1.2); staticMethod(99); setInstanceMemberVariable(5); int i = getInstanceMemberVariable(); setStaticMemberVariable(10); i = getStaticMemberVariable(); } } 21.7 Common customization featuresAn earlier section presented the absolute basics of C/C++ wrapping. If you do nothing but feed SWIG a header file, you will get an interface that mimics the behavior described. However, sometimes this isn't enough to produce a nice module. Certain types of functionality might be missing or the interface to certain functions might be awkward. This section describes some common SWIG features that are used to improve the interface to existing C/C++ code. 21.7.1 C/C++ helper functionsSometimes when you create a module, it is missing certain bits of functionality. For example, if you had a function like this typedef struct Image {...}; void set_transform(Image *im, double m[4][4]);
it would be accessible from Java, but there may be no easy way to call it. The problem here is that a type wrapper class is generated for the two dimensional array parameter so there is no easy way to construct and manipulate a suitable %inline %{ /* Note: double[4][4] is equivalent to a pointer to an array double (*)[4] */ double (*new_mat44())[4] { return (double (*)[4]) malloc(16*sizeof(double)); } void free_mat44(double (*x)[4]) { free(x); } void mat44_set(double x[4][4], int i, int j, double v) { x[i][j] = v; } double mat44_get(double x[4][4], int i, int j) { return x[i][j]; } %} From Java, you could then write code like this: Image im = new Image(); SWIGTYPE_p_a_4__double a = example.new_mat44(); example.mat44_set(a,0,0,1.0); example.mat44_set(a,1,1,1.0); example.mat44_set(a,2,2,1.0); ... example.set_transform(im,a); example.free_mat44(a); Admittedly, this is not the most elegant looking approach. However, it works and it wasn't too hard to implement. It is possible to improve on this using Java code, typemaps, and other customization features as covered in later sections, but sometimes helper functions are a quick and easy solution to difficult cases. 21.7.2 Class extension with %extendOne of the more interesting features of SWIG is that it can extend structures and classes with new methods or constructors. Here is a simple example: %module example %{ #include "someheader.h" %} struct Vector { double x,y,z; }; %extend Vector { char *toString() { static char tmp[1024]; sprintf(tmp,"Vector(%g,%g,%g)", $self->x,$self->y,$self->z); return tmp; } Vector(double x, double y, double z) { Vector *v = (Vector *) malloc(sizeof(Vector)); v->x = x; v->y = y; v->z = z; return v; } }; Now, in Java Vector v = new Vector(2,3,4); System.out.println(v); will display Vector(2,3,4)
21.7.3 Exception handling with %exception and %javaexception
If a C or C++ function throws an error, you may want to convert that error into a Java exception. To do this, you can use the In C, a function often indicates an error by returning a status code (a negative number or a NULL pointer perhaps). Here is a simple example of how you might handle that: %exception malloc { $action if (!result) { jclass clazz = (*jenv)->FindClass(jenv, "java/lang/OutOfMemoryError"); (*jenv)->ThrowNew(jenv, clazz, "Not enough memory"); return $null; } } void *malloc(size_t nbytes); In Java, SWIGTYPE_p_void a = example.malloc(2000000000); will produce a familiar looking Java exception: Exception in thread "main" java.lang.OutOfMemoryError: Not enough memory at exampleJNI.malloc(Native Method) at example.malloc(example.java:16) at runme.main(runme.java:112) If a library provides some kind of general error handling framework, you can also use that. For example: %exception malloc { $action if (err_occurred()) { jclass clazz = (*jenv)->FindClass(jenv, "java/lang/OutOfMemoryError"); (*jenv)->ThrowNew(jenv, clazz, "Not enough memory"); return $null; } } void *malloc(size_t nbytes);
If no declaration name is given to C++ exceptions are also easy to handle. We can catch the C++ exception and rethrow it as a Java exception like this: %exception getitem { try { $action } catch (std::out_of_range &e) { jclass clazz = jenv->FindClass("java/lang/Exception"); jenv->ThrowNew(clazz, "Range error"); return $null; } } class FooClass { public: FooClass *getitem(int index); // Might throw std::out_of_range exception ... };
In the example above, %javaexception("java.lang.Exception") getitem { try { $action } catch (std::out_of_range &e) { jclass clazz = jenv->FindClass("java/lang/Exception"); jenv->ThrowNew(clazz, "Range error"); return $null; } } class FooClass { public: FooClass *getitem(int index); // Might throw std::out_of_range exception ... };
The generated proxy method now generates a throws clause containing public class FooClass { ... public FooClass getitem(int index) throws java.lang.Exception { ... } ... } The examples above first use the C JNI calling syntax then the C++ JNI calling syntax. The C++ calling syntax will not compile as C and also vice versa. It is however possible to write JNI calls which will compile under both C and C++ and is covered in the Typemaps for both C and C++ compilation section.
The language-independent 21.7.4 Method access with %javamethodmodifiers
A Java feature called %javamethodmodifiers protect_me() "protected"; void protect_me(); Will produce the method in the module class with protected access. protected static void protect_me() { exampleJNI.protect_me(); } 21.8 Tips and techniquesAlthough SWIG is largely automatic, there are certain types of wrapping problems that require additional user input. Examples include dealing with output parameters, strings and arrays. This chapter discusses the common techniques for solving these problems. 21.8.1 Input and output parameters using primitive pointers and referencesA common problem in some C programs is handling parameters passed as simple pointers or references. For example: void add(int x, int y, int *result) { *result = x + y; } or perhaps int sub(int *x, int *y) { return *x-*y; }
The %module example %include "typemaps.i" void add(int, int, int *OUTPUT); int sub(int *INPUT, int *INPUT); In Java, this allows you to pass simple values. For example: int result = example.sub(7,4); System.out.println("7 - 4 = " + result); int[] sum = {0}; example.add(3,4,sum); System.out.println("3 + 4 = " + sum[0]); Which will display: 7 - 4 = 3 3 + 4 = 7
Notice how the
If you don't want to use the names %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); If a function mutates one of its parameters like this, void negate(int *x) { *x = -(*x); }
you can use %include "typemaps.i" ... void negate(int *INOUT); In Java, the input parameter is the first element in a 1 element array and is replaced by the output of the function. For example: int[] neg = {3}; example.negate(neg); System.out.println("Negative of 3 = " + neg[0]); And no prizes for guessing the output: Negative of 3 = -3
These typemaps can also be applied to C++ references. The above examples would work the same if they had been defined using references instead of pointers. For example, the Java code to use the void negate(int *INOUT); or using a reference: void negate(int &INOUT); Note: Since most Java primitive types are immutable and are passed by value, it is not possible to perform in-place modification of a type passed as a parameter.
Be aware that the primary purpose of the void foo(Bar *OUTPUT);
will not have the intended effect since 21.8.2 Simple pointers
If you must work with simple pointers such as %module example %include "cpointer.i" %inline %{ extern void add(int x, int y, int *result); %} %pointer_functions(int, intp);
The int *new_intp(); int *copy_intp(int *x); void delete_intp(int *x); void intp_assign(int *x, int value); int intp_value(int *x); In Java, you would use the functions like this: SWIGTYPE_p_int intPtr = example.new_intp(); example.add(3,4,intPtr); int result = example.intp_value(intPtr); System.out.println("3 + 4 = " + result);
If you replace intp intPtr = new intp(); example.add(3,4,intPtr.cast()); int result = intPtr.value(); System.out.println("3 + 4 = " + result); See the SWIG Library chapter for further details. 21.8.3 Wrapping C arrays with Java arrays
SWIG can wrap arrays in a more natural Java manner than the default by using the %include "arrays_java.i"; int array[4]; void populate(int x[]) { int i; for (i=0; i<4; i++) x[i] = 100 + i; } These one dimensional arrays can then be used as if they were Java arrays: int[] array = new int[4]; example.populate(array); System.out.print("array: "); for (int i=0; i<array.length; i++) System.out.print(array[i] + " "); example.setArray(array); int[] global_array = example.getArray(); System.out.print("\nglobal_array: "); for (int i=0; i<array.length; i++) System.out.print(global_array[i] + " "); Java arrays are always passed by reference, so any changes a function makes to the array will be seen by the calling function. Here is the output after running this code: array: 100 101 102 103 global_array: 100 101 102 103
Note that for assigning array variables the length of the C variable is used, so it is possible to use a Java array that is bigger than the C code will cope with. Only the number of elements in the C array will be used. However, if the Java array is not large enough then you are likely to get a segmentation fault or access violation, just like you would in C. When arrays are used in functions like Please be aware that the typemaps in this library are not efficient as all the elements are copied from the Java array to a C array whenever the array is passed to and from JNI code. There is an alternative approach using the SWIG array library and this is covered in the next section. 21.8.4 Unbounded C ArraysSometimes a C function expects an array to be passed as a pointer. For example, int sumitems(int *first, int nitems) { int i, sum = 0; for (i = 0; i < nitems; i++) { sum += first[i]; } return sum; }
One of the ways to wrap this is to apply the Java array typemaps that come in the %include "arrays_java.i" %apply int[] {int *};
The int[] array = new int[10000000]; // Array of 10-million integers for (int i=0; i<array.length; i++) { // Set some values array[i] = i; } int sum = example.sumitems(array,10000); System.out.println("Sum = " + sum); and the sum would be displayed: Sum = 49995000
This approach is probably the most natural way to use arrays. However, it suffers from performance problems when using large arrays as a lot of copying of the elements occurs in transferring the array from the Java world to the C++ world. An alternative approach to using Java arrays for C arrays is to use an alternative SWIG library file %include "carrays.i" %array_functions(int, intArray);
The int *new_intArray(int nelements); void delete_intArray(int *x); int intArray_getitem(int *x, int index); void intArray_setitem(int *x, int index, int value); In Java, you would use the functions like this: SWIGTYPE_p_int array = example.new_intArray(10000000); // Array of 10-million integers for (int i=0; i<10000; i++) { // Set some values example.intArray_setitem(array,i,i); } int sum = example.sumitems(array,10000); System.out.println("Sum = " + sum);
If you replace %include "carrays.i" %array_class(int, intArray);
The intArray array = new intArray(10000000); // Array of 10-million integers for (int i=0; i<10000; i++) { // Set some values array.setitem(i,i); } int sum = example.sumitems(array.cast(),10000); System.out.println("Sum = " + sum);
The array “object” created by 21.8.5 Overriding new and delete to allocate from Java heapUnlike some languages supported by SWIG, Java has a true garbage collection subsystem. Other languages will free SWIG wrapped objects when their reference count reaches zero. Java only schedules these objects for finalization, which may not occur for some time. Because SWIG objects are allocated on the C heap, Java users may find the JVM memory use quickly exceeds the assigned limits, as memory fills with unfinalized proxy objects. Forcing garbage collection is clearly an undesirable solution. An elegant fix for C++ users is to override new and delete using the following code (here shown included in a SWIG interface file) /* File: java_heap.i */ %module test %{ #include <stdexcept> #include "jni.h" /** * A stash area embedded in each allocation to hold java handles */ struct Jalloc { jbyteArray jba; jobject ref; }; static JavaVM *cached_jvm = 0; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { cached_jvm = jvm; return JNI_VERSION_1_2; } static JNIEnv * JNU_GetEnv() { JNIEnv *env; jint rc = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2); if (rc == JNI_EDETACHED) throw std::runtime_error("current thread not attached"); if (rc == JNI_EVERSION) throw std::runtime_error("jni version not supported"); return env; } void * operator new(size_t t) { if (cached_jvm != 0) { JNIEnv *env = JNU_GetEnv(); jbyteArray jba = env->NewByteArray((int) t + sizeof(Jalloc)); if (env->ExceptionOccurred()) throw bad_alloc(); void *jbuffer = static_cast<void *>(env->GetByteArrayElements(jba, 0)); if (env->ExceptionOccurred()) throw bad_alloc(); Jalloc *pJalloc = static_cast<Jalloc *>(jbuffer); pJalloc->jba = jba; /* Assign a global reference so byte array will persist until delete'ed */ pJalloc->ref = env->NewGlobalRef(jba); if (env->ExceptionOccurred()) throw bad_alloc(); return static_cast<void *>(static_cast<char *>(jbuffer) + sizeof(Jalloc)); } else { /* JNI_OnLoad not called, use malloc and mark as special */ Jalloc *pJalloc = static_cast<Jalloc *>(malloc((int) t + sizeof(Jalloc))); if (!pJalloc) throw bad_alloc(); pJalloc->ref = 0; return static_cast<void *>( static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); } } void operator delete(void *v) { if (v != 0) { void *buffer = static_cast<void *>( static_cast<char *>(v) - sizeof(Jalloc)); Jalloc *pJalloc = static_cast<Jalloc *>(buffer); if (pJalloc->ref) { JNIEnv *env = JNU_GetEnv(); env->DeleteGlobalRef(pJalloc->ref); env->ReleaseByteArrayElements(pJalloc->jba, static_cast<jbyte *>(buffer), 0); } else { free(buffer); } } } %} ... This code caches the Java environment during initialization, and when new is called, a Java ByteArray is allocated to provide the SWIG objects with space in the Java heap. This has the combined effect of re-asserting the Java virtual machine's limit on memory allocation, and puts additional pressure on the garbage collection system to run more frequently. This code is made slightly more complicated because allowances must be made if new is called before the JNI_OnLoad is executed. This can happen during static class initialization, for example. Unfortunately, because most Java implementations call malloc and free, this solution will not work for C wrapped structures. However, you are free to make functions that allocate and free memory from the Java heap using this model and use these functions in place of malloc and free in your own code. 21.9 Java typemaps
This section describes how you can modify SWIG's default wrapping behavior for various C/C++ datatypes using the
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 generated code. 21.9.1 Default primitive type mappingsThe following table lists the default type mapping from Java to C/C++.
Note that SWIG wraps the C Given the following C function: void func(unsigned short a, char *b, const long &c, unsigned long long d); The module class method would be: public static void func(int a, String b, int c, java.math.BigInteger d) {...} The intermediary JNI class would use the same types: public final static native void func(int jarg1, String jarg2, int jarg3, java.math.BigInteger jarg4); and the JNI function would look like this: SWIGEXPORT void JNICALL Java_exampleJNI_func(JNIEnv *jenv, jclass jcls, jint jarg1, jstring jarg2, jint jarg3, jobject jarg4) {...}
The mappings for C 21.9.2 Default typemaps for non-primitive types
The previous section covered the primitive type mappings. Non-primitive types such as classes and structs are mapped using pointers on the C/C++ side and storing the pointer into a Java
So in summary, the C/C++ pointer to non-primitive types is cast into the 64 bit Java 21.9.3 Sixty four bit JVMsIf you are using a 64 bit JVM you may have to override the C long, but probably not C int default mappings. Mappings will be system dependent, for example long will need remapping on Unix LP64 systems (long, pointer 64 bits, int 32 bits), but not on Microsoft 64 bit Windows which will be using a P64 IL32 (pointer 64 bits and int, long 32 bits) model. This may be automated in a future version of SWIG. Note that the Java write once run anywhere philosophy holds true for all pure Java code when moving to a 64 bit JVM. Unfortunately it won't of course hold true for JNI code. 21.9.4 What is a typemap?A typemap is nothing more than a code generation rule that is attached to a specific C datatype. For example, to convert integers from Java to C, you might define a typemap like this: %module example %typemap(in) int { $1 = $input; printf("Received an integer : %d\n", $1); } %inline %{ extern int fact(int nonnegative); %}
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 When this example is compiled into a Java module, it can be used as follows: System.out.println(example.fact(6)); and the output will be: Received an integer : 6 720
In this example, the typemap is applied to all occurrences of the %module example %typemap(in) int nonnegative { $1 = $input; printf("Received an integer : %d\n", $1); } %inline %{ extern int fact(int nonnegative); %}
In this case, the typemap code is only attached to arguments that exactly match
The application of a typemap to specific datatypes and argument names involves more than simple text-matching–typemaps are fully integrated into the SWIG C++ type-system. When you define a typemap for %typemap(in) int nonnegative { $1 = $input; printf("Received an integer : %d\n", $1); } %inline %{ typedef int Integer; extern int fact(Integer nonnegative); // Above typemap is applied %}
However, the matching of Typemaps can also be defined for groups of consecutive arguments. For example: %typemap(in) (char *str, int len) { ... }; int count(char c, char *str, int len); When a multi-argument typemap is defined, the arguments are always handled as a single Java parameter. This allows the function to be used like this (notice how the length parameter is omitted): int c = example.count('e',"Hello World"); 21.9.5 Typemaps for mapping C/C++ types to Java typesThe typemaps available to the Java module include the common typemaps listed in the main typemaps section. There are a number of additional typemaps which are necessary for using SWIG with Java. The most important of these implement the mapping of C/C++ types to Java types:
If you are writing your own typemaps to handle a particular type, you will normally have to write a collection of them. The default typemaps are in “ The “jni”, “jtype” and “jstype” typemaps are usually defined together to handle the Java to C/C++ type mapping. An “in” typemap should be accompanied by a “javain” typemap and likewise an “out” typemap by a “javaout” typemap. If an “in” typemap is written, a “freearg” and “argout” typemap may also need to be written as some types have a default “freearg” and/or “argout” typemap which may need overriding. The “freearg” typemap sometimes releases memory allocated by the “in” typemap. The “argout” typemap sometimes sets values in function parameters which are passed by reference in Java.
Note that the “in” typemap marshals the JNI type held in the “jni” typemap to the real C/C++ type and for the opposite direction, the “out” typemap marshals the real C/C++ type to the JNI type held in the “jni” typemap. For non-primitive types the “in” and “out” typemaps are responsible for casting between the C/C++ pointer and the 64 bit short a; short* pa = 0; int i = 0x1234; a = (short)i; /* okay */ a = *(short*)&i; /* breaks aliasing rules */ An email posting, Aliasing, pointer casts and gcc 3.3 elaborates further on the subject. In SWIG, the “in” and “out” typemaps for pointers are typically %typemap(in) struct Foo * %{ $1 = *(struct Foo **)&$input; /* cast jlong into C ptr */ %} %typemap(out) struct Bar * %{ *(struct Bar **)&$result = $1; /* cast C ptr into jlong */ %} struct Bar {...}; struct Foo {...}; struct Bar * FooBar(struct Foo *f); resulting in the following code which breaks the aliasing rules: SWIGEXPORT jlong JNICALL Java_exampleJNI_FooBar(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jlong jresult = 0 ; struct Foo *arg1 = (struct Foo *) 0 ; struct Bar *result = 0 ; (void)jenv; (void)jcls; (void)jarg1_; arg1 = *(struct Foo **)&jarg1; result = (struct Bar *)FooBar(arg1); *(struct Bar **)&jresult = result; return jresult; } If you are using gcc as your C compiler, you might get a “dereferencing type-punned pointer will break strict-aliasing rules” warning about this. Please see Compiling a dynamic module to avoid runtime problems with these strict aliasing rules.
The default code generated by SWIG for the Java module comes from the typemaps in the “
21.9.6 Java typemap attributesThere are a few additional typemap attributes that the Java module supports. The first of these is the 'throws' attribute. The throws attribute is optional and specified after the typemap name and contains one or more comma separated classes for adding to the throws clause for any methods that use that typemap. It is analogous to the %javaexception feature's throws attribute. %typemap(typemapname, throws="ExceptionClass1, ExceptionClass2") type { ... } The attribute is necessary for supporting Java checked exceptions and can be added to just about any typemap. The list of typemaps include all the C/C++ (JNI) typemaps in the “Typemaps” chapter and the Java specific typemaps listed in the previous section, barring the “jni”, “jtype” and “jstype” typemaps as they could never contain code to throw an exception. The throws clause is generated for the proxy method as well as the JNI method in the JNI intermediary class. If a method uses more than one typemap and each of those typemaps have classes specified in the throws clause, the union of the exception classes is added to the throws clause ensuring there are no duplicate classes. See the NaN exception example for further usage. The “jtype” typemap has the optional 'nopgcpp' attribute which can be used to suppress the generation of the premature garbage collection prevention parameter. The “javain” typemap has the optional 'pre', 'post' and 'pgcppname' attributes. These are used for generating code before and after the JNI call in the proxy class or module class. The 'pre' attribute contains code that is generated before the JNI call and the 'post' attribute contains code generated after the JNI call. The 'pgcppname' attribute is used to change the premature garbage collection prevention parameter name passed to the JNI function. This is sometimes needed when the 'pre' typemap creates a temporary variable which is then passed to the JNI function. Note that when the 'pre' or 'post' attributes are specified and the associated type is used in a constructor, a constructor helper function is generated. This is necessary as the Java proxy constructor wrapper makes a call to a support constructor using a this call. In Java the this call must be the first statement in the constructor body. The constructor body thus calls the helper function and the helper function instead makes the JNI call, ensuring the 'pre' code is called before the JNI call is made. There is a Date marshalling example showing 'pre', 'post' and 'pgcppname' attributes in action. 21.9.7 Java special variables
The standard SWIG special variables are available for use within typemaps as described in the Typemaps documentation , for example The Java module uses a few additional special variables:
%typemap(check) int * %{ if (error) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error"); return $null; } %} If the typemap gets put into a function with void as return, $null will expand to nothing: SWIGEXPORT void JNICALL Java_jnifn(...) { if (error) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error"); return ; } ... } otherwise $null expands to NULL SWIGEXPORT jobject JNICALL Java_jnifn(...) { if (error) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error"); return NULL; } ... }
Here is an example: %typemap(javain) Class "Class.getCPtr($javainput)" %typemap(javain) unsigned short "$javainput" %typemap(javaout) Class * { return new Class($jnicall, $owner); } %inline %{ class Class {...}; Class * bar(Class cls, unsigned short ush) { return new Class(); }; %} The generated proxy code is then: public static Class bar(Class cls, int ush) { return new Class(exampleJNI.bar(Class.getCPtr(cls), cls, ush), false); }
Here $javainput has been replaced by %newobject bar(Class cls, unsigned short ush);
The generated code constructs the return type using public static Class bar(Class cls, int ush) { return new Class(exampleJNI.bar(Class.getCPtr(cls), cls, ush), true); }
21.9.8 Typemaps for both C and C++ compilationJNI calls must be written differently depending on whether the code is being compiled as C or C++. For example C compilation requires the pointer to a function pointer struct member syntax like const jclass clazz = (*jenv)->FindClass(jenv, "java/lang/String"); whereas C++ code compilation of the same function call is a member function call using a class pointer like const jclass clazz = jenv->FindClass("java/lang/String"); To enable typemaps to be used for either C or C++ compilation, a set of JCALLx macros have been defined in Lib/java/javahead.swg, where x is the number of arguments in the C++ version of the JNI call. The above JNI calls would be written in a typemap like this const jclass clazz = JCALL1(FindClass, jenv, "java/lang/String"); Note that the SWIG preprocessor expands these into the appropriate C or C++ JNI calling convention. The C calling convention is emitted by default and the C++ calling convention is emitted when using the -c++ SWIG commandline option. If you do not intend your code to be targeting both C and C++ then your typemaps can use the appropriate JNI calling convention and need not use the JCALLx macros. 21.9.9 Java code typemapsMost of SWIG's typemaps are used for the generation of C/C++ code. The typemaps in this section are used solely for the generation of Java code. Elements of proxy classes and type wrapper classes come from the following typemaps (the defaults).
base (extends) for Java class: empty default
the essential support body for proxy classes (proxy base classes only), typewrapper classes and enum classes. Default contains extra constructors, memory ownership control member variables (
the essential support body for proxy classes (derived classes only). Same as “javabody” typemap, but only used for proxy derived classes.
class modifiers for the Java class: default is “public class”
Java code is copied verbatim to the Java class: empty default
destructor wrapper - the
destructor wrapper - the
import statements for Java class: empty default
interfaces (extends) for Java class: empty default
the Compatibility Note: In SWIG-1.3.21 and earlier releases, typemaps called “javagetcptr” and “javaptrconstructormodifiers” were available. These are deprecated and the “javabody” typemap can be used instead. In summary the contents of the typemaps make up a proxy class like this: [ javaimports typemap ] [ javaclassmodifiers typemap ] javaclassname extends [ javabase typemap ] implements [ javainterfaces typemap ] { [ javabody or javabody_derived typemap ] [ javafinalize typemap ] public synchronized void delete() [ javadestruct OR javadestruct_derived typemap ] [ javacode typemap ] ... proxy functions ... }
Note the The type wrapper class is similar in construction: [ javaimports typemap ] [ javaclassmodifiers typemap ] javaclassname extends [ javabase typemap ] implements [ javainterfaces typemap ] { [ javabody typemap ] [ javacode typemap ] } The enum class is also similar in construction: [ javaimports typemap ] [ javaclassmodifiers typemap ] javaclassname extends [ javabase typemap ] implements [ javainterfaces typemap ] { ... Enum values ... [ javabody typemap ] [ javacode typemap ] } The “javaimports” typemap is ignored if the enum class is wrapped by an inner Java class, that is when wrapping an enum declared within a C++ class.
The defaults can be overridden to tailor these classes. Here is an example which will change the %typemap(javabody) SWIGTYPE %{ private long swigCPtr; protected boolean swigCMemOwn; public $javaclassname(long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; } public static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } %}
The typemap code is the same that is in “ For the typemap to be used in all type wrapper classes, all the different types that type wrapper classes could be used for should be targeted: %typemap(javabody) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{ private long swigCPtr; public $javaclassname(long cPtr, boolean bFutureUse) { swigCPtr = cPtr; } protected $javaclassname() { swigCPtr = 0; } public static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } %}
Again this is the same that is in “ 21.9.10 Director specific typemapsThe Java directors feature requires the “javadirectorin”, “javadirectorout”, “directorin” and the “directorout” typemaps in order to work properly. The “javapackage” typemap is an optional typemap used to identify the Java package path for individual SWIG generated proxy classes.
The “directorin” typemap is used for converting arguments in the C++ director class to the appropriate JNI type before the upcall to Java. This typemap also specifies the JNI field descriptor for the type in the “descriptor” attribute. For example, integers are converted as follows: %typemap(directorin,descriptor="I") int "$input = (jint) $1;"
%typemap(directorin,descriptor="Ljava/lang/String;") char * %{ $input = jenv->NewStringUTF($1); %}
User-defined types have the default “descriptor” attribute “
The “directorout” typemap is used for converting the JNI return type in the C++ director class to the appropriate C++ type after the upcall to Java. For example, integers are converted as follows: %typemap(directorout) int %{ $result = (int)$input; %}
%typemap(directorout) char * { $1 = 0; if ($input) { $result = (char *)jenv->GetStringUTFChars($input, 0); if (!$1) return $null; } }
Conversion from jtype to jstype for director methods. These are Java code typemaps which transform the type used in the Java intermediary JNI class (as specified in the “jtype” typemap) to the Java type used in the Java module class, proxy classes and type wrapper classes (as specified in the “jstype” typemap). This typemap provides the conversion for the parameters in the director methods when calling up from C++ to Java. For primitive types, this typemap is usually specified as: %typemap(javadirectorin) int "$jniinput"
The
Conversion from jstype to jtype for director methods. These are Java code typemaps which transform the type used in the Java module class, proxy classes and type wrapper classes (as specified in the “jstype” typemap) to the type used in the Java intermediary JNI class (as specified in the “jtype” typemap). This typemap provides the conversion for the return type in the director methods when returning from the C++ to Java upcall. For primitive types, this typemap is usually specified as: %typemap(javadirectorout) int "$javacall"
The
The “javapackage” typemap is optional; it serves to identify a class's Java package. This typemap should be used in conjunction with classes that are defined outside of the current SWIG interface file. For example: // class Foo is handled in a different interface file: %import "Foo.i" %feature("director") Example; %inline { class Bar { }; class Example { public: virtual ~Example(); void ping(Foo *arg1, Bar *arg2); }; } Assume that the Foo class is part of the Java package com.wombat.foo but the above interface file is part of the Java package com.wombat.example. Without the “javapackage” typemap, SWIG will assume that the Foo class belongs to com.wombat.example class. The corrected interface file looks like: // class Foo is handled in a different interface file: %import "Foo.i" %typemap("javapackage") Foo, Foo *, Foo & "com.wombat.foo"; %feature("director") Example; %inline { class Bar { }; class Example { public: virtual ~Example(); void ping(Foo *arg1, Bar *arg2); }; }
SWIG looks up the package based on the actual type (plain Foo, Foo pointer and Foo reference), so it is important to associate all three types with the desired package. Practically speaking, you should create a separate SWIG interface file, which is %import-ed into each SWIG interface file, when you have multiple Java packages. Note the helper macros below, %typemap("javapackage") SWIGTYPE, SWIGTYPE *, SWIGTYPE & "package.for.most.classes"; %define OTHER_PACKAGE_SPEC(TYPE...) %typemap("javapackage") TYPE, TYPE *, TYPE & "package.for.other.classes"; %enddef %define ANOTHER_PACKAGE_SPEC(TYPE...) %typemap("javapackage") TYPE, TYPE *, TYPE & "package.for.another.set"; %enddef OTHER_PACKAGE_SPEC(Package_2_class_one) ANOTHER_PACKAGE_SPEC(Package_3_class_two) /* etc */ The basic strategy here is to provide a default package typemap for the majority of the classes, only providing “javapackage” typemaps for the exceptions. 21.10 Typemap Examples
This section includes a few examples of typemaps. For more examples, you might look at the files “ 21.10.1 Simpler Java enums for enums without initializersThe default Proper Java enums approach to wrapping enums is somewhat verbose. This is to handle all possible C/C++ enums, in particular enums with initializers. The generated code can be simplified if the enum being wrapped does not have any initializers.
The following shows how to remove the support methods that are generated by default and instead use the methods in the Java enum base class %include "enums.swg" %typemap(javain) enum SWIGTYPE "$javainput.ordinal()" %typemap(javaout) enum SWIGTYPE { return $javaclassname.class.getEnumConstants()[$jnicall]; } %typemap(javabody) enum SWIGTYPE "" %inline %{ enum HairType { blonde, ginger, brunette }; void setHair(HairType h); HairType getHair(); %} SWIG will generate the following Java enum, which is somewhat simpler than the default: public enum HairType { blonde, ginger, brunette; } and the two Java proxy methods will be: public static void setHair(HairType h) { exampleJNI.setHair(h.ordinal()); } public static HairType getHair() { return HairType.class.getEnumConstants()[exampleJNI.getHair()]; }
For marshalling Java enums to C/C++ enums, the These typemaps can often be used as the default for wrapping enums as in many cases there won't be any enum initializers. In fact a good strategy is to always use these typemaps and to specifically handle enums with initializers using %apply. This would be done by using the original versions of these typemaps in “enums.swg” under another typemap name for applying using %apply. 21.10.2 Handling C++ exception specifications as Java exceptions
This example demonstrates various ways in which C++ exceptions can be tailored and converted into Java exceptions. Let's consider a simple file class %include "std_string.i" // for std::string typemaps #include <string> class FileException { std::string message; public: FileException(const std::string& msg) : message(msg) {} std::string what() { return message; } }; class SimpleFile { std::string filename; public: SimpleFile(const std::string& filename) : filename(filename) {} void open() throw(FileException) { ... } };
As the %typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); return $null; %}
Basically SWIG will generate a C++ try catch block and the body of the “throws” typemap constitutes the catch block. The above typemap calls a SWIG supplied method which throws a %typemap(throws, throws="java.io.IOException") FileException { jclass excep = jenv->FindClass("java/io/IOException"); if (excep) jenv->ThrowNew(excep, $1.what().c_str()); return $null; }
Note that this typemap uses the 'throws' typemap attribute to ensure a throws clause is generated. The generated proxy method then specifies the checked exception by containing public class SimpleFile { ... public void open() throws java.io.IOException { ... } }
Lastly, if you don't want to map your C++ exception into one of the standard Java exceptions, the C++ class can be wrapped and turned into a custom Java exception class. If we go back to our example, the first thing we must do is get SWIG to wrap %typemap(javabase) FileException "java.lang.Exception"; %typemap(javacode) FileException %{ public String getMessage() { return what(); } %} This generates: public class FileException extends java.lang.Exception { ... public String getMessage() { return what(); } public FileException(String msg) { ... } public String what() { return exampleJNI.FileException_what(swigCPtr, this); } }
We could alternatively have used 21.10.3 NaN Exception - exception handling for a particular type
A Java exception can be thrown from any Java or JNI code. Therefore, as most typemaps contain either Java or JNI code, just about any typemap could throw an exception. The following example demonstrates exception handling on a type by type basis by checking for 'Not a number' (NaN) whenever a parameter of type Consider the following C++ code: bool calculate(float first, float second);
To validate every %module example %typemap(javain) float "$module.CheckForNaN($javainput)" %pragma(java) modulecode=%{ /** Simply returns the input value unless it is not a number, whereupon an exception is thrown. */ static protected float CheckForNaN(float num) { if (Float.isNaN(num)) throw new RuntimeException("Not a number"); return num; } %}
Note that the public class example { ... /** Simply returns the input value unless it is not a number, whereupon an exception is thrown. */ static protected float CheckForNaN(float num) { if (Float.isNaN(num)) throw new RuntimeException("Not a number"); return num; } public static boolean calculate(float first, float second) { return exampleJNI.calculate(example.CheckForNaN(first), example.CheckForNaN(second)); } }
Note that the “javain” typemap is used for every occurrence of a The exception checking could alternatively have been placed into the 'pre' attribute that the “javain” typemap supports. The “javain” typemap above could be replaced with the following: %typemap(javain, pre=" $module.CheckForNaN($javainput);") float "$javainput"
which would modify the public class example { ... public static boolean calculate(float first, float second) { example.CheckForNaN(first); example.CheckForNaN(second); { return exampleJNI.calculate(first, second); } } } See the Date marshalling example for an example using further “javain” typemap attributes.
If we decide that what we actually want is a checked exception instead of a runtime exception, we can change this easily enough. The proxy method that uses %typemap(javain, throws="java.lang.Exception") float "$module.CheckForNaN($javainput)" %pragma(java) modulecode=%{ /** Simply returns the input value unless it is not a number, whereupon an exception is thrown. */ static protected float CheckForNaN(float num) throws java.lang.Exception { if (Float.isNaN(num)) throw new RuntimeException("Not a number"); return num; } %}
The public class example { ... /** Simply returns the input value unless it is not a number, whereupon an exception is thrown. */ static protected float CheckForNaN(float num) throws java.lang.Exception { if (Float.isNaN(num)) throw new RuntimeException("Not a number"); return num; } public static boolean calculate(float first, float second) throws java.lang.Exception { return exampleJNI.calculate(example.CheckForNaN(first), example.CheckForNaN(second)); } } If we were a martyr to the JNI cause, we could replace the succinct code within the “javain” typemap with a few pages of JNI code. If we had, we would have put it in the “in” typemap which, like all JNI and Java typemaps, also supports the 'throws' attribute. 21.10.4 Converting Java String arrays to char %%**%%
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 Java String array to be used as a %module example /* This tells SWIG to treat char ** as a special case when used as a parameter in a function call */ %typemap(in) char ** (jint size) { int i = 0; size = (*jenv)->GetArrayLength(jenv, $input); $1 = (char **) malloc((size+1)*sizeof(char *)); /* make a copy of each string */ for (i = 0; i<size; i++) { jstring j_string = (jstring)(*jenv)->GetObjectArrayElement(jenv, $input, i); const char * c_string = (*jenv)->GetStringUTFChars(jenv, j_string, 0); $1[i] = malloc((strlen(c_string)+1)*sizeof(char)); strcpy($1[i], c_string); (*jenv)->ReleaseStringUTFChars(jenv, j_string, c_string); (*jenv)->DeleteLocalRef(jenv, j_string); } $1[i] = 0; } /* This cleans up the memory we malloc'd before the function call */ %typemap(freearg) char ** { int i; for (i=0; i<size$argnum-1; i++) free($1[i]); free($1); } /* This allows a C function to return a char ** as a Java String array */ %typemap(out) char ** { int i; int len=0; jstring temp_string; const jclass clazz = (*jenv)->FindClass(jenv, "java/lang/String"); while ($1[len]) len++; jresult = (*jenv)->NewObjectArray(jenv, len, clazz, NULL); /* exception checking omitted */ for (i=0; i<len; i++) { temp_string = (*jenv)->NewStringUTF(jenv, *result++); (*jenv)->SetObjectArrayElement(jenv, jresult, i, temp_string); (*jenv)->DeleteLocalRef(jenv, temp_string); } } /* These 3 typemaps tell SWIG what JNI and Java types to use */ %typemap(jni) char ** "jobjectArray" %typemap(jtype) char ** "String[]" %typemap(jstype) char ** "String[]" /* These 2 typemaps handle the conversion of the jtype to jstype typemap type and vice versa */ %typemap(javain) char ** "$javainput" %typemap(javaout) char ** { return $jnicall; } /* Now a few 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; } char **get_args() { static char *values[] = { "Dave", "Mike", "Susan", "John", "Michelle", 0}; return &values[0]; } %} Note that the 'C' JNI calling convention is used. Checking for any thrown exceptions after JNI function calls has been omitted. When this module is compiled, our wrapped C functions can be used by the following Java program: // File runme.java public class runme { static { try { System.loadLibrary("example"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. " + e); System.exit(1); } } public static void main(String argv[]) { String animals[] = {"Cat","Dog","Cow","Goat"}; example.print_args(animals); String args[] = example.get_args(); for (int i=0; i<args.length; i++) System.out.println(i + ":" + args[i]); } } When compiled and run we get: $ java runme argv[0] = Cat argv[1] = Dog argv[2] = Cow argv[3] = Goat 0:Dave 1:Mike 2:Susan 3:John 4:Michelle In the example, a few different typemaps are used. The “in” typemap is used to receive an input argument and convert it to a C array. Since dynamic memory allocation is used to allocate memory for the array, the “freearg” typemap is used to later release this memory after the execution of the C function. The “out” typemap is used for function return values. Lastly the “jni”, “jtype” and “jstype” typemaps are also required to specify what Java types to use. 21.10.5 Expanding a Java object to multiple argumentsSuppose that you had a collection of C functions with arguments such as the following: int foo(int argc, char **argv);
In the previous example, a typemap was written to pass a Java String array as the example.foo(4, new String[]{"red", "green", "blue", "white"}); Although this works, it's a little awkward to specify the argument count. To fix this, a multi-argument typemap can be defined. This is not very difficult–you only have to make slight modifications to the previous example's typemaps: %typemap(in) (int argc, char **argv) { int i = 0; $1 = (*jenv)->GetArrayLength(jenv, $input); $2 = (char **) malloc(($1+1)*sizeof(char *)); /* make a copy of each string */ for (i = 0; i<$1; i++) { jstring j_string = (jstring)(*jenv)->GetObjectArrayElement(jenv, $input, i); const char * c_string = (*jenv)->GetStringUTFChars(jenv, j_string, 0); $2[i] = malloc((strlen(c_string)+1)*sizeof(char)); strcpy($2[i], c_string); (*jenv)->ReleaseStringUTFChars(jenv, j_string, c_string); (*jenv)->DeleteLocalRef(jenv, j_string); } $2[i] = 0; } %typemap(freearg) (int argc, char **argv) { int i; for (i=0; i<$1-1; i++) free($2[i]); free($2); } %typemap(jni) (int argc, char **argv) "jobjectArray" %typemap(jtype) (int argc, char **argv) "String[]" %typemap(jstype) (int argc, char **argv) "String[]" %typemap(javain) (int argc, char **argv) "$javainput"
When writing a multiple-argument typemap, each of the types is referenced by a variable such as With the above typemap in place, you will find it no longer necessary to supply the argument count. This is automatically set by the typemap code. For example: example.foo(new String[]{"red", "green", "blue", "white"}); 21.10.6 Using typemaps to return arguments
A common problem in some C programs is that values may be returned in function parameters rather than in the return value of a function. The
Now we are going to outline an alternative approach to using arrays for C pointers. The INOUT typemap uses a Here is our example function: /* Returns a status value and two values in out1 and out2 */ int spam(double a, double b, double *out1, double *out2);
If we define a structure %module example /* Define a new structure to use instead of double * */ %inline %{ typedef struct { double value; } MyDouble; %} %{ /* Returns a status value and two values in out1 and out2 */ int spam(double a, double b, double *out1, double *out2) { int status = 1; *out1 = a*10.0; *out2 = b*100.0; return status; }; %} /* This typemap will make any double * function parameters with name OUTVALUE take an argument of MyDouble instead of double *. This will allow the calling function to read the double * value after returning from the function. */ %typemap(in) double *OUTVALUE { jclass clazz = jenv->FindClass("MyDouble"); jfieldID fid = jenv->GetFieldID(clazz, "swigCPtr", "J"); jlong cPtr = jenv->GetLongField($input, fid); MyDouble *pMyDouble = NULL; *(MyDouble **)&pMyDouble = *(MyDouble **)&cPtr; $1 = &pMyDouble->value; } %typemap(jtype) double *OUTVALUE "MyDouble" %typemap(jstype) double *OUTVALUE "MyDouble" %typemap(jni) double *OUTVALUE "jobject" %typemap(javain) double *OUTVALUE "$javainput" /* Now we apply the typemap to the named variables */ %apply double *OUTVALUE { double *out1, double *out2 }; int spam(double a, double b, double *out1, double *out2); Note that the C++ JNI calling convention has been used this time and so must be compiled as C++ and the -c++ commandline must be passed to SWIG. JNI error checking has been omitted for clarity.
What the typemaps do are make the named // File: runme.java public class runme { static { try { System.loadLibrary("example"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. " + e); System.exit(1); } } public static void main(String argv[]) { MyDouble out1 = new MyDouble(); MyDouble out2 = new MyDouble(); int ret = example.spam(1.2, 3.4, out1, out2); System.out.println(ret + " " + out1.getValue() + " " + out2.getValue()); } } When compiled and run we get: $ java runme 1 12.0 340.0 21.10.7 Adding Java downcasts to polymorphic return typesSWIG support for polymorphism works in that the appropriate virtual function is called. However, the default generated code does not allow for downcasting. Let's examine this with the following code: %include "std_string.i" #include <iostream> using namespace std; class Vehicle { public: virtual void start() = 0; ... }; class Ambulance : public Vehicle { string vol; public: Ambulance(string volume) : vol(volume) {} virtual void start() { cout << "Ambulance started" << endl; } void sound_siren() { cout << vol << " siren sounded!" << endl; } ... }; Vehicle *vehicle_factory() { return new Ambulance("Very loud"); } If we execute the following Java code: Vehicle vehicle = example.vehicle_factory(); vehicle.start(); Ambulance ambulance = (Ambulance)vehicle; ambulance.sound_siren(); We get: Ambulance started java.lang.ClassCastException at runme.main(runme.java:16)
Even though we know from examination of the C++ code that The first is not to use a Java cast but a call to C++ to make the cast. Add this to your code: %exception Ambulance::dynamic_cast(Vehicle *vehicle) { $action if (!result) { jclass excep = jenv->FindClass("java/lang/ClassCastException"); if (excep) { jenv->ThrowNew(excep, "dynamic_cast exception"); } } } %extend Ambulance { static Ambulance *dynamic_cast(Vehicle *vehicle) { return dynamic_cast<Ambulance *>(vehicle); } }; It would then be used from Java like this Ambulance ambulance = Ambulance.dynamic_cast(vehicle); ambulance.sound_siren();
Should %typemap(out) Vehicle * { Ambulance *downcast = dynamic_cast<Ambulance *>($1); *(Ambulance **)&$result = downcast; } %typemap(javaout) Vehicle * { return new Ambulance($jnicall, $owner); }
Here we are using our knowledge that class FireEngine : public Vehicle { public: FireEngine() {} virtual void start() { cout << "FireEngine started" << endl; } void roll_out_hose() { cout << "Hose rolled out" << endl; } ... }; Vehicle *vehicle_factory(int vehicle_number) { if (vehicle_number == 0) return new Ambulance("Very loud"); else return new FireEngine(); } To be able to downcast with this sort of Java code: FireEngine fireengine = (FireEngine)example.vehicle_factory(1); fireengine.roll_out_hose(); Ambulance ambulance = (Ambulance)example.vehicle_factory(0); ambulance.sound_siren();
the following typemaps targeted at the %typemap(jni) Vehicle *vehicle_factory "jobject" %typemap(jtype) Vehicle *vehicle_factory "Vehicle" %typemap(jstype) Vehicle *vehicle_factory "Vehicle" %typemap(javaout) Vehicle *vehicle_factory { return $jnicall; } %typemap(out) Vehicle *vehicle_factory { Ambulance *ambulance = dynamic_cast<Ambulance *>($1); FireEngine *fireengine = dynamic_cast<FireEngine *>($1); if (ambulance) { // call the Ambulance(long cPtr, boolean cMemoryOwn) constructor jclass clazz = jenv->FindClass("Ambulance"); if (clazz) { jmethodID mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); if (mid) { jlong cptr = 0; *(Ambulance **)&cptr = ambulance; $result = jenv->NewObject(clazz, mid, cptr, false); } } } else if (fireengine) { // call the FireEngine(long cPtr, boolean cMemoryOwn) constructor jclass clazz = jenv->FindClass("FireEngine"); if (clazz) { jmethodID mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); if (mid) { jlong cptr = 0; *(FireEngine **)&cptr = fireengine; $result = jenv->NewObject(clazz, mid, cptr, false); } } } else { cout << "Unexpected type " << endl; } if (!$result) cout << "Failed to create new java object" << endl; } Better error handling would need to be added into this code. There are other solutions to this problem, but this last example demonstrates some more involved JNI code. SWIG usually generates code which constructs the proxy classes using Java code as it is easier to handle error conditions and is faster. Note that the JNI code above uses a number of string lookups to call a constructor, whereas this would not occur using byte compiled Java code. 21.10.8 Adding an equals method to the Java classes
When a pointer is returned from a JNI function, it is wrapped using a new Java proxy class or type wrapper class. Even when the pointers are the same, it will not be possible to know that the two Java classes containing those pointers are actually the same object. It is common in Java to use the %typemap(javacode) SWIGTYPE %{ public boolean equals(Object obj) { boolean equal = false; if (obj instanceof $javaclassname) equal = ((($javaclassname)obj).swigCPtr == this.swigCPtr); return equal; } public int hashCode() { return (int)getPointer(); } %} class Foo { }; Foo* returnFoo(Foo *foo) { return foo; }
The following would display Foo foo1 = new Foo(); Foo foo2 = example.returnFoo(foo1); System.out.println("foo1? " + foo1.equals(foo2)); 21.10.9 Void pointers and a common Java base class
One might wonder why the common code that SWIG emits for the proxy and type wrapper classes is not pushed into a base class. The reason is that although %typemap(javabase) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "SWIG" %typemap(javacode) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{ protected long getPointer() { return swigCPtr; } %} Define new base class called SWIG: public abstract class SWIG { protected abstract long getPointer(); public boolean equals(Object obj) { boolean equal = false; if (obj instanceof SWIG) equal = (((SWIG)obj).getPointer() == this.getPointer()); return equal; } SWIGTYPE_p_void getVoidPointer() { return new SWIGTYPE_p_void(getPointer(), false); } } This example contains some useful functionality which you may want in your code.
21.10.10 Struct pointer to pointer
Pointers to pointers are often used as output parameters in C factory type functions. These are a bit more tricky to handle. Consider the following situation where a typedef struct { int hoursAvailable; char *greeting; } Butler; // Note: HireButler will allocate the memory // The caller must free the memory by calling FireButler()!! extern int HireButler(Butler **ppButler); extern void FireButler(Butler *pButler); C code implementation: int HireButler(Butler **ppButler) { Butler *pButler = (Butler *)malloc(sizeof(Butler)); pButler->hoursAvailable = 24; pButler->greeting = (char *)malloc(32); strcpy(pButler->greeting, "At your service Sir"); *ppButler = pButler; return 1; } void FireButler(Butler *pButler) { free(pButler->greeting); free(pButler); } Let's take two approaches to wrapping this code. The first is to provide a functional interface, much like the original C interface. The following Java code shows how we intend the code to be used: Butler jeeves = new Butler(); example.HireButler(jeeves); System.out.println("Greeting: " + jeeves.getGreeting()); System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day"); example.FireButler(jeeves); Resulting in the following output when run: Greeting: At your service Sir Availability: 24 hours per day
Note the usage is very much like it would be used if we were writing C code, that is, explicit memory management is needed. No C memory is allocated in the construction of the %module example // Do not generate the default proxy constructor or destructor %nodefaultctor Butler; %nodefaultdtor Butler; // Add in pure Java code proxy constructor %typemap(javacode) Butler %{ /** This constructor creates the proxy which initially does not create nor own any C memory */ public Butler() { this(0, false); } %} // Type typemaps for marshalling Butler ** %typemap(jni) Butler ** "jobject" %typemap(jtype) Butler ** "Butler" %typemap(jstype) Butler ** "Butler" // Typemaps for Butler ** as a parameter output type %typemap(in) Butler ** (Butler *ppButler = 0) %{ $1 = &ppButler; %} %typemap(argout) Butler ** { // Give Java proxy the C pointer (of newly created object) jclass clazz = (*jenv)->FindClass(jenv, "Butler"); jfieldID fid = (*jenv)->GetFieldID(jenv, clazz, "swigCPtr", "J"); jlong cPtr = 0; *(Butler **)&cPtr = *$1; (*jenv)->SetLongField(jenv, $input, fid, cPtr); } %typemap(javain) Butler ** "$javainput"
Note that the JNI code sets the proxy's Note: The old %nodefault directive disabled the default constructor and destructor at the same time. This is unsafe in most of the cases, and you can use the explicit %nodefaultctor and %nodefaultdtor directives to achieve the same result if needed.
The second approach offers a more object oriented interface to the Java user. We do this by making the Java proxy class's constructor call the Butler jeeves = new Butler(); System.out.println("Greeting: " + jeeves.getGreeting()); System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day");
Note that the Butler class is used just like any other Java class and no extra coding by the user needs to be written to clear up the underlying C memory as the finalizer will be called by the garbage collector which in turn will call the // Don't expose the memory allocation/de-allocation functions %ignore FireButler(Butler *pButler); %ignore HireButler(Butler **ppButler); // Add in a custom proxy constructor and destructor %extend Butler { Butler() { Butler *pButler = 0; HireButler(&pButler); return pButler; } ~Butler() { FireButler($self); } }
Note that the code in 21.10.11 Memory management when returning references to member variablesThis example shows how to prevent premature garbage collection of objects when the underlying C++ class returns a pointer or reference to a member variable. Consider the following C++ code: struct Wheel { int size; Wheel(int sz) : size(sz) {} }; class Bike { Wheel wheel; public: Bike(int val) : wheel(val) {} Wheel& getWheel() { return wheel; } }; and the following usage from Java after running the code through SWIG: Wheel wheel = new Bike(10).getWheel(); System.out.println("wheel size: " + wheel.getSize()); // Simulate a garbage collection System.gc(); System.runFinalization(); System.out.println("wheel size: " + wheel.getSize()); Don't be surprised that if the resulting output gives strange results such as… wheel size: 10 wheel size: 135019664
What has happened here is the garbage collector has collected the %typemap(javacode) Wheel %{ // Ensure that the GC doesn't collect any Bike instance set from Java private Bike bikeReference; protected void addReference(Bike bike) { bikeReference = bike; } %} // Add a Java reference to prevent premature garbage collection and resulting use // of dangling C++ pointer. Intended for methods that return pointers or // references to a member variable. %typemap(javaout) Wheel& getWheel { long cPtr = $jnicall; $javaclassname ret = null; if (cPtr != 0) { ret = new $javaclassname(cPtr, $owner); ret.addReference(this); } return ret; }
The code in the first typemap gets added to the public class Wheel { ... // Ensure that the GC doesn't collect any bike set from Java private Bike bikeReference; protected void addReference(Bike bike) { bikeReference = bike; } } public class Bike { ... public Wheel getWheel() { long cPtr = exampleJNI.Bike_getWheel(swigCPtr, this); Wheel ret = null; if (cPtr != 0) { ret = new Wheel(cPtr, false); ret.addReference(this); } return ret; } }
Note the 21.10.12 Memory management for objects passed to the C++ layerManaging memory can be tricky when using C++ and Java proxy classes. The previous example shows one such case and this example looks at memory management for a class passed to a C++ method which expects the object to remain in scope after the function has returned. Consider the following two C++ classes: struct Element { int value; Element(int val) : value(val) {} }; class Container { Element* element; public: Container() : element(0) {} void setElement(Element* e) { element = e; } Element* getElement() { return element; } }; and usage from C++ Container container; Element element(20); container.setElement(&element); cout << "element.value: " << container.getElement()->value << endl; and more or less equivalent usage from Java Container container = new Container(); container.setElement(new Element(20)); System.out.println("element value: " + container.getElement().getValue()); The C++ code will always print out 20, but the value printed out may not be this in the Java equivalent code. In order to understand why, consider a garbage collection occuring… Container container = new Container(); container.setElement(new Element(20)); // Simulate a garbage collection System.gc(); System.runFinalization(); System.out.println("element value: " + container.getElement().getValue());
The temporary element created with public class Container { ... // Ensure that the GC doesn't collect any Element set from Java // as the underlying C++ class stores a shallow copy private Element elementReference; private long getCPtrAndAddReference(Element element) { elementReference = element; return Element.getCPtr(element); } public void setElement(Element e) { exampleJNI.Container_setElement(swigCPtr, this, getCPtrAndAddReference(e), e); } }
The following typemaps will generate the desired code. The 'javain' typemap matches the input parameter type for the %typemap(javain) Element *e "getCPtrAndAddReference($javainput)" %typemap(javacode) Container %{ // Ensure that the GC doesn't collect any element set from Java // as the underlying C++ class stores a shallow copy private Element elementReference; private long getCPtrAndAddReference(Element element) { elementReference = element; return Element.getCPtr(element); } %} 21.10.13 Date marshalling using the javain typemap and associated attributes
The NaN Exception example is a simple example of the “javain” typemap and its 'pre' attribute. This example demonstrates how a C++ date class, say class CDate { public: CDate(int year, int month, int day); int getYear(); int getMonth(); int getDay(); ... }; struct Action { static int doSomething(const CDate &dateIn, CDate &dateOut); Action(const CDate &date, CDate &dateOut); };
Note that
First let's look at the code that is generated by default, where the Java proxy class public class Action { ... public static int doSomething(CDate dateIn, CDate dateOut) { return exampleJNI.Action_doSomething(CDate.getCPtr(dateIn), dateIn, CDate.getCPtr(dateOut), dateOut); } public Action(CDate date, CDate dateOut) { this(exampleJNI.new_Action(CDate.getCPtr(date), date, CDate.getCPtr(dateOut), dateOut), true); } }
The %typemap(jstype) SWIGTYPE & "$javaclassname" %typemap(javain) SWIGTYPE & "$javaclassname.getCPtr($javainput)"
where '$javaclassname' is translated into the proxy class name, java.util.GregorianCalendar calendarIn = new java.util.GregorianCalendar(2011, java.util.Calendar.APRIL, 13, 0, 0, 0); java.util.GregorianCalendar calendarOut = new java.util.GregorianCalendar(); // Note in calls below, calendarIn remains unchanged and calendarOut // is set to a new value by the C++ call Action.doSomething(calendarIn, calendarOut); Action action = new Action(calendarIn, calendarOut);
To achieve this mapping, we need to alter the default code generation slightly so that at the Java layer, a %typemap(jstype) const CDate& "java.util.GregorianCalendar" %typemap(javain, pre=" CDate temp$javainput = new CDate($javainput.get(java.util.Calendar.YEAR), " "$javainput.get(java.util.Calendar.MONTH), $javainput.get(java.util.Calendar.DATE));", pgcppname="temp$javainput") const CDate & "$javaclassname.getCPtr(temp$javainput)" %typemap(jstype) CDate& "java.util.Calendar" %typemap(javain, pre=" CDate temp$javainput = new CDate($javainput.get(java.util.Calendar.YEAR), " "$javainput.get(java.util.Calendar.MONTH), $javainput.get(java.util.Calendar.DATE));", post=" $javainput.set(temp$javainput.getYear(), temp$javainput.getMonth(), " "temp$javainput.getDay(), 0, 0, 0);", pgcppname="temp$javainput") CDate & "$javaclassname.getCPtr(temp$javainput)"
The resulting generated proxy code in the public class Action { ... public static int doSomething(java.util.GregorianCalendar dateIn, java.util.Calendar dateOut) { CDate tempdateIn = new CDate(dateIn.get(java.util.Calendar.YEAR), dateIn.get(java.util.Calendar.MONTH), dateIn.get(java.util.Calendar.DATE)); CDate tempdateOut = new CDate(dateOut.get(java.util.Calendar.YEAR), dateOut.get(java.util.Calendar.MONTH), dateOut.get(java.util.Calendar.DATE)); try { return exampleJNI.Action_doSomething(CDate.getCPtr(tempdateIn), tempdateIn, CDate.getCPtr(tempdateOut), tempdateOut); } finally { dateOut.set(tempdateOut.getYear(), tempdateOut.getMonth(), tempdateOut.getDay(), 0, 0, 0); } } static private long SwigConstructAction(java.util.GregorianCalendar date, java.util.Calendar dateOut) { CDate tempdate = new CDate(date.get(java.util.Calendar.YEAR), date.get(java.util.Calendar.MONTH), date.get(java.util.Calendar.DATE)); CDate tempdateOut = new CDate(dateOut.get(java.util.Calendar.YEAR), dateOut.get(java.util.Calendar.MONTH), dateOut.get(java.util.Calendar.DATE)); try { return exampleJNI.new_Action(CDate.getCPtr(tempdate), tempdate, CDate.getCPtr(tempdateOut), tempdateOut); } finally { dateOut.set(tempdateOut.getYear(), tempdateOut.getMonth(), tempdateOut.getDay(), 0, 0, 0); } } public Action(java.util.GregorianCalendar date, java.util.Calendar dateOut) { this(Action.SwigConstructAction(date, dateOut), true); } } A few things to note:
21.11 Living with Java DirectorsThis section is intended to address frequently asked questions and frequently encountered problems when using Java directors.
%template(VectorOfInt) std::vector<int>;
{ Foo darg1 = new Foo(jarg1, false); self.method_upcall(darg1); } Unfortunately, this loses the Java type information that is part of the underlying Foo director proxy class's Java object pointer causing the type cast to fail. The SWIG Java module's director code attempts to correct the problem, but only for director-enabled classes, since the director class retains a global reference to its Java object. Thus, for director-enabled classes and only for director-enabled classes, the generated proxy Java code looks something like: public static void MyClass_method_upcall(MyClass self, long jarg1, Foo jarg1_object) { Foo darg1 = (jarg1_object != null ? jarg1_object : new Foo(jarg1, false)); self.method_upcall(darg1);
}
When you import a SWIG interface file containing class definitions, the classes you want to be director-enabled must be have the public void method_upcall(Foo foo_object) { FooDerived derived = (foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object) : null); %%/*%% rest of your code here %%*/%% } } An good approach for managing downcasting is placing a static method in each derived class that performs the downcast from the superclass, e.g., public class FooDerived extends Foo { %%/*%% ... %%*/%% public static FooDerived downcastFooDerived(Foo foo_object) { try { return (foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object); } catch (ClassCastException exc) { %%//%% Wasn't a FooDerived object, some other subclass of Foo return null; } } } Then change the code in MyClassDerived as follows: public class MyClassDerived extends MyClass { %%/*%% ... %%*/%% public void method_upcall(Foo foo_object) { FooDerived derived = FooDerived.downcastFooDerived(foo_object); %%/*%% rest of your code here %%*/%% } }
/** Make sure user overrides this method, it's where the upcall
*/ public abstract void method_upcall(Foo foo_object); %%///%% Downcast from Foo to UserVisibleFoo public static UserVisibleFoo downcastUserVisibleFoo(Foo foo_object) { try { return (foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object) : null); } catch (ClassCastException exc) { %%//%% Wasn't a FooDerived object, some other subclass of Foo return null; } }
}
This doesn't prevent the user from creating subclasses derived from Foo, however, UserVisibleFoo provides the safety net that reminds the user to override the 21.12 Odds and ends21.12.1 JavaDoc comments
The SWIG documentation system is currently deprecated. When it is resurrected JavaDoc comments will be fully supported. If you can't wait for the full documentation system a couple of workarounds are available. The %javamethodmodifiers Barmy::lose_marbles() " /** * Calling this method will make you mad. * Use with <b>utmost</b> caution. */ public"; %typemap(javaimports) Barmy " /** The crazy class. Use as a last resort. */" class Barmy { public: void lose_marbles() {} };
Note the “public” added at the end of the /** The crazy class. Use as a last resort. */ public class Barmy { ... /** * Calling this method will make you mad. * Use with <b>utmost</b> caution. */ public void lose_marbles() { ... } ... } 21.12.2 Functional interface without proxy classesIt is possible to run SWIG in a mode that does not produce proxy classes by using the -noproxy commandline option. The interface is rather primitive when wrapping structures or classes and is accessed through function calls to the module class. All the functions in the module class are wrapped by functions with identical names as those in the intermediary JNI class. Consider the example we looked at when examining proxy classes: class Foo { public: int x; int spam(int num, Foo* foo); };
When using public class example { public static void Foo_x_get(SWIGTYPE_p_Foo self, int x) {...} public static int Foo_x_get(SWIGTYPE_p_Foo self) {...} public static int Foo_spam(SWIGTYPE_p_Foo self, int num, SWIGTYPE_p_Foo foo) {...} public static SWIGTYPE_p_Foo new_Foo() {...} public static void delete_Foo(SWIGTYPE_p_Foo self) {...} } This approach is not nearly as natural as using proxy classes as the functions need to be used like this: SWIGTYPE_p_Foo foo = example.new_Foo(); example.Foo_x_set(foo, 10); int var = example.Foo_x_get(foo); example.Foo_spam(foo, 20, foo); example.delete_Foo(foo);
Unlike proxy classes, there is no attempt at tracking memory. All destructors have to be called manually for example the 21.12.3 Using your own JNI functions
You may have some hand written JNI functions that you want to use in addition to the SWIG generated JNI functions. Adding these to your SWIG generated package is possible using the %native (HandRolled) void HandRolled(int, char *); %{ JNIEXPORT void JNICALL Java_packageName_moduleName_HandRolled(JNIEnv *, jclass, jlong, jstring); %}
No C JNI function will be generated and the public final static native void HandRolled(int jarg1, String jarg2); and as usual this function is wrapped by another which for a global C function would appear in the module class: public static void HandRolled(int arg0, String arg1) { exampleJNI.HandRolled(arg0, arg1); }
The
In summary the 21.12.4 Performance concerns and hints
If you're directly manipulating huge arrays of complex objects from Java, performance may suffer greatly when using the array functions in
Java classes without any finalizers generally speed up code execution as there is less for the garbage collector to do. Finalizer generation can be stopped by using an empty %typemap(javafinalize) SWIGTYPE ""
However, you will have to be careful about memory management and make sure that you code in a call to the 21.12.5 DebuggingThe generated code can be debugged using both a Java debugger and a C++ debugger using the usual debugging techniques. Breakpoints can be set in either Java or C++ code and so both can be debugged simultaneously. Most debuggers do not understand both Java and C++, with one noteable exception of Sun Studio, where it is possible to step from Java code into a JNI method within one environment.
Alternatively, debugging can involve placing debug printout statements in the JNI layer using the
The 21.13 Examples
The directory Examples/java has a number of further examples. Take a look at these if you want to see some of the techniques described in action. The Examples/index.html file in the parent directory contains the SWIG Examples Documentation and is a useful starting point. If your SWIG installation went well Unix users should be able to type 22 SWIG and Common LispCommon Lisp is a high-level, all-purpose, object-oriented, dynamic, functional programming language with long history. Common Lisp is used in many fields, ranging from web development to finance, and also common in computer science education. There are more than 9 different implementations of common lisp which are available, all have different foreign function interfaces. SWIG currently supports only the Allegro Common Lisp, Common Foreign Function Interface(CFFI), CLisp and UFFI foreign function interfaces. 22.1 Allegro Common LispAllegro Common Lisp support in SWIG has been updated to include support for both C and C++. You can read about the interface here 22.2 Common Foreign Function Interface(CFFI)CFFI, the Common Foreign Function Interface, is a portable foreign function interface for ANSI Common Lisp systems, similar in spirit to UFFI. Unlike UFFI, CFFI requires only a small set of low-level functionality from the Lisp implementation, such as calling a foreign function by name, allocating foreign memory, and dereferencing pointers. To run the cffi module of SWIG requires very little effort, you just need to run: swig -cffi -module module-name file-name But a better was of using all the power of SWIG is to write SWIG interface files. Below we will explain how to write interface files and the various things which you can do with them. 22.2.1 Additional Commandline OptionsThe following table list the additional commandline options available for the CLISP module. They can also be seen by using: swig -cffi -help
22.2.2 Generating CFFI bindingsAs we mentioned earlier the ideal way to use SWIG is to use interface files. To illustrate the use of it, lets assume that we have a file named test.h with the following C code: #define y 5 #define x (y >> 1) typedef int days; struct bar { short p, q; char a, b; int *z[1000]; struct bar * n; }; struct bar * my_struct; struct foo { int a; struct foo * b[100]; }; int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int p); int func123(div_t * p,int **q[100],int r[][1000][10]); void lispsort_double (int n, double * array); enum color { RED, BLUE, GREEN}; Corresponding to this we will write a simple interface file: %module test %include "test.h" The generated SWIG Code will be: ;;;SWIG wrapper code starts here (cl:defmacro defanonenum (&body enums) "Converts anonymous enums to defconstants." `(cl:progn ,@(cl:loop for value in enums for index = 0 then (cl:1+ index) when (cl:listp value) do (cl:setf index (cl:second value) value (cl:first value)) collect `(cl:defconstant ,value ,index)))) (cl:eval-when (:compile-toplevel :load-toplevel) (cl:unless (cl:fboundp 'swig-lispify) (cl:defun swig-lispify (name flag cl:&optional (package cl:*package*)) (cl:labels ((helper (lst last rest cl:&aux (c (cl:car lst))) (cl:cond ((cl:null lst) rest) ((cl:upper-case-p c) (helper (cl:cdr lst) 'upper (cl:case last ((lower digit) (cl:list* c #\- rest)) (cl:t (cl:cons c rest))))) ((cl:lower-case-p c) (helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest))) ((cl:digit-char-p c) (helper (cl:cdr lst) 'digit (cl:case last ((upper lower) (cl:list* c #\- rest)) (cl:t (cl:cons c rest))))) ((cl:char-equal c #\_) (helper (cl:cdr lst) '_ (cl:cons #\- rest))) (cl:t (cl:error "Invalid character: ~A" c))))) (cl:let ((fix (cl:case flag ((constant enumvalue) "+") (variable "*") (cl:t "")))) (cl:intern (cl:concatenate 'cl:string fix (cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil)) fix) package)))))) ;;;SWIG wrapper code ends here (cl:defconstant y 5) (cl:defconstant x (cl:ash 5 -1)) (cffi:defcstruct bar (p :short) (q :short) (a :char) (b :char) (z :pointer) (n :pointer)) (cffi:defcvar ("my_struct" my_struct) :pointer) (cffi:defcstruct foo (a :int) (b :pointer)) (cffi:defcfun ("pointer_func" pointer_func) :int (ClosureFun :pointer) (p :int)) (cffi:defcfun ("func123" func123) :int (p :pointer) (q :pointer) (r :pointer)) (cffi:defcfun ("lispsort_double" lispsort_double) :void (n :int) (array :pointer)) (cffi:defcenum color :RED :BLUE :GREEN) The SWIG wrapper code refers to the special code which SWIG may need to use while wrapping C code. You can turn on/off the generation of this code by using the -[no]swig-lisp option. You must have noticed that SWIG goes one extra step to ensure that CFFI does not do automatic lispification of the C function names. The reason SWIG does this is because quite often developers want to build a nice CLOS based lispy API, and this one to one correspondence between C function names and lisp function name helps. Maybe you want to have your own convention for generating lisp function names for corresponding C function names, or you just want to lispify the names, also, before we forget you want to export the generated lisp names. To do this, we will use the SWIG feature directive. Let's edit the interface file such that the C type “div_t*” is changed to Lisp type “:my-pointer”, we lispify all names, export everything, and do some more stuff. %module test %typemap(cin) div_t* ":my-pointer"; %feature("intern_function","1"); %feature("export"); %feature("inline") lispsort_double; %feature("intern_function", "my-lispify") lispsort_double; %rename func123 renamed_cool_func; %ignore "pointer_func"; %include "test.h" The typemap(cin) ensures that for all arguments which are input to C with the type “div_t*”, the “:my-pointer” type be used. Similarly typemap(cout) are used for all types which are returned from C. The feature intern_function ensures that all C names are interned using the swig-lispify function. The “1” given to the feature is optional. The use of feature like %feature(“intern_function”,“1”); globally enables interning for everything. If you want to target a single function, or declaration then use the targeted version of feature, %feature(“intern_function”, “my-lispify”) lispsort_double;, here we are using an additional feature which allows us to use our lispify function. The export feature allows us to export the symbols. The inline feature declaims the declared function as inline. The rename directive allows us to change the name(it is useful when generating C wrapper code for handling overloaded functions). The ignore directive ignores a certain declaration. There are several other things which are possible, to see some example of usage of SWIG look at the Lispbuilder and wxCL projects. The generated code with 'noswig-lisp' option is: (cl:defconstant #.(swig-lispify "y" 'constant) 5) (cl:export '#.(swig-lispify "y" 'constant)) (cl:defconstant #.(swig-lispify "x" 'constant) (cl:ash 5 -1)) (cl:export '#.(swig-lispify "x" 'constant)) (cffi:defcstruct #.(swig-lispify "bar" 'classname) (#.(swig-lispify "p" 'slotname) :short) (#.(swig-lispify "q" 'slotname) :short) (#.(swig-lispify "a" 'slotname) :char) (#.(swig-lispify "b" 'slotname) :char) (#.(swig-lispify "z" 'slotname) :pointer) (#.(swig-lispify "n" 'slotname) :pointer)) (cl:export '#.(swig-lispify "bar" 'classname)) (cl:export '#.(swig-lispify "p" 'slotname)) (cl:export '#.(swig-lispify "q" 'slotname)) (cl:export '#.(swig-lispify "a" 'slotname)) (cl:export '#.(swig-lispify "b" 'slotname)) (cl:export '#.(swig-lispify "z" 'slotname)) (cl:export '#.(swig-lispify "n" 'slotname)) (cffi:defcvar ("my_struct" #.(swig-lispify "my_struct" 'variable)) :pointer) (cl:export '#.(swig-lispify "my_struct" 'variable)) (cffi:defcstruct #.(swig-lispify "foo" 'classname) (#.(swig-lispify "a" 'slotname) :int) (#.(swig-lispify "b" 'slotname) :pointer)) (cl:export '#.(swig-lispify "foo" 'classname)) (cl:export '#.(swig-lispify "a" 'slotname)) (cl:export '#.(swig-lispify "b" 'slotname)) (cffi:defcfun ("renamed_cool_func" #.(swig-lispify "renamed_cool_func" 'function)) :int (p :my-pointer) (q :pointer) (r :pointer)) (cl:export '#.(swig-lispify "renamed_cool_func" 'function)) (cl:declaim (cl:inline #.(my-lispify "lispsort_double" 'function))) (cffi:defcfun ("lispsort_double" #.(my-lispify "lispsort_double" 'function)) :void (n :int) (array :pointer)) (cl:export '#.(my-lispify "lispsort_double" 'function)) (cffi:defcenum #.(swig-lispify "color" 'enumname) #.(swig-lispify "RED" 'enumvalue :keyword) #.(swig-lispify "BLUE" 'enumvalue :keyword) #.(swig-lispify "GREEN" 'enumvalue :keyword)) (cl:export '#.(swig-lispify "color" 'enumname)) 22.2.3 Generating CFFI bindings for C++ codeThis feature to SWIG (for CFFI) is very new and still far from complete. Pitch in with your patches, bug reports and feature requests to improve it. Generating bindings for C++ code, requires -c++ option to be present and it first generates C binding which will wrap the C++ code, and then generates the corresponding CFFI wrapper code. In the generated C wrapper code, you will often want to put your own C code, such as the code to include various files. This can be done by making use of “%{” and “%}” as shown below. %{ #include "Test/test.h" %} Also, while parsing the C++ file and generating C wrapper code SWIG may need to be able to understand various symbols used in other header files. To help SWIG in doing this while ensuring that wrapper code is generated for the target file, use the “import” directive. The “include” directive specifies the target file for which wrapper code will be generated. %import "ancillary/header.h" %include "target/header.h" Various features which were available for C headers can also be used here. The target header which we are going to use here is: namespace OpenDemo { class Test { public: float x; // constructors Test (void) {x = 0;} Test (float X) {x = X;} // vector addition Test operator+ (const Test& v) const {return Test (x+v.x);} // length squared float lengthSquared (void) const {return this->dot (*this);} static float distance (const Test& a, const Test& b){return(a-b).length();} inline Test parallelComponent (const Test& unitBasis) const { return unitBasis * projection; } Test setYtoZero (void) const {return Test (this->x);} static const Test zero; }; inline Test operator* (float s, const Test& v) {return v*s;} inline std::ostream& operator<< (std::ostream& o, const Test& v) { return o << "(" << v.x << ")"; } inline Test RandomUnitVectorOnXZPlane (void) { return RandomVectorInUnitRadiusSphere().setYtoZero().normalize(); } } The interface used is: %module test %include "test.cpp" SWIG generates 3 files, the first one is a C wrap which we don't show, the second is the plain CFFI wrapper which is as shown below: (cffi:defcfun ("_wrap_Test_x_set" Test_x_set) :void (self :pointer) (x :float)) (cffi:defcfun ("_wrap_Test_x_get" Test_x_get) :float (self :pointer)) (cffi:defcfun ("_wrap_new_Test__SWIG_0" new_Test) :pointer) (cffi:defcfun ("_wrap_new_Test__SWIG_1" new_Test) :pointer (X :float)) (cffi:defcfun ("_wrap_Test___add__" Test___add__) :pointer (self :pointer) (v :pointer)) (cffi:defcfun ("_wrap_Test_lengthSquared" Test_lengthSquared) :float (self :pointer)) (cffi:defcfun ("_wrap_Test_distance" Test_distance) :float (a :pointer) (b :pointer)) (cffi:defcfun ("_wrap_Test_parallelComponent" Test_parallelComponent) :pointer (self :pointer) (unitBasis :pointer)) (cffi:defcfun ("_wrap_Test_setYtoZero" Test_setYtoZero) :pointer (self :pointer)) (cffi:defcvar ("Test_zero" Test_zero) :pointer) (cffi:defcfun ("_wrap_delete_Test" delete_Test) :void (self :pointer)) (cffi:defcfun ("_wrap___mul__" __mul__) :pointer (s :float) (v :pointer)) (cffi:defcfun ("_wrap___lshift__" __lshift__) :pointer (o :pointer) (v :pointer)) (cffi:defcfun ("_wrap_RandomUnitVectorOnXZPlane" RandomUnitVectorOnXZPlane) :pointer) The output is pretty good but it fails in disambiguating overloaded functions such as the constructor, in this case. One way of resolving this problem is to make the interface use the rename directiv, but hopefully there are better solutions. In addition SWIG also generates, a CLOS file (clos:defclass test() ((ff :reader ff-pointer))) (clos:defmethod (cl:setf x) (arg0 (obj test)) (Test_x_set (ff-pointer obj) arg0)) (clos:defmethod x ((obj test)) (Test_x_get (ff-pointer obj))) (cl:shadow "+") (clos:defmethod + ((obj test) (self test) (v test)) (Test___add__ (ff-pointer obj) (ff-pointer self) (ff-pointer v))) (clos:defmethod length-squared ((obj test) (self test)) (Test_lengthSquared (ff-pointer obj) (ff-pointer self))) (clos:defmethod parallel-component ((obj test) (self test) (unitBasis test)) (Test_parallelComponent (ff-pointer obj) (ff-pointer self) (ff-pointer unitBasis))) (clos:defmethod set-yto-zero ((obj test) (self test)) (Test_setYtoZero (ff-pointer obj) (ff-pointer self))) I agree that the CFFI C++ module needs lot more work. But I hope it provides a starting point, on which you can base your work of importing C++ libraries to Lisp. If you have any questions, suggestions, patches, etc., related to CFFI module feel free to contact us on the SWIG mailing list, and also please add a “[CFFI]” tag in the subject line. 22.2.4 Inserting user code into generated files
It is often necessary to include user-defined code into the automatically generated interface files. For example, when building a C++ interface, example_wrap.cxx will likely not compile unless you add a %module example %{ #include "header.h" %} %include "header.h" int fact(int n); Additional sections have been added for inserting into the generated lisp interface file:
Note that the block 22.3 CLISPCLISP is a feature-loaded implementation of common lisp which is portable across most of the operating system environments and hardware. CLISP includes an interpreter, a compiler, a debugger, CLOS, MOP, a foreign language interface, i18n, regular expressions, a socket interface, and more. An X11 interface is available through CLX, Garnet and CLUE/CLIO. Command line editing is provided by readline. CLISP runs Maxima, ACL2 and many other Common Lisp packages. To run the clisp module of SWIG requires very little effort, you just need to execute: swig -clisp -module module-name file-name Because of the high level nature of the CLISP FFI, the bindings generated by SWIG may not be absolutely correct, and you may need to modify them. The good thing is that you don't need to complex interface file for the CLISP module. The CLISP module tries to produce code which is both human readable and easily modifyable. 22.3.1 Additional Commandline OptionsThe following table list the additional commandline options available for the CLISP module. They can also be seen by using: swig -clisp -help
22.3.2 Details on CLISP bindings
As mentioned earlier the CLISP bindings generated by SWIG may need some modifications. The clisp module creates a lisp file with the same name as the module name. This lisp file contains a 'defpackage' declaration, with the package name same as the module name. This package uses the 'common-lisp' and 'ffi' packages. Also, package exports all the functions, structures and variables for which an ffi binding was generated. (defpackage :test (:use :common-lisp :ffi) (:export :make-bar :bar-x :bar-y :bar-a :bar-b :bar-z :bar-n :pointer_func :func123 :make-cfunr :lispsort_double :test123)) (in-package :test) (default-foreign-language :stdc) The ffi wrappers for functions and variables are generated as shown below. When functions have arguments of type “double * array”, SWIG doesn't knows whether it is an 'out' argument or it is an array which will be passed, so SWIG plays it safe by declaring it as an '(array (ffi:c-ptr DOUBLE-FLOAT))'. For arguments of type “int **z[100]” where SWIG has more information, i.e., it knows that 'z' is an array of pointers to pointers of integers, SWIG defines it to be '(z (ffi:c-ptr (ffi:c-array (ffi:c-ptr (ffi:c-ptr ffi:int)) 100)))' extern "C" { int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int y); int func123(div_t * x,int **z[100],int y[][1000][10]); void lispsort_double (int n, double * array); void test123(float x , double y); } (ffi:def-call-out pointer_func (:name "pointer_func") (:arguments (ClosureFun (ffi:c-function (:arguments (arg0 (ffi:c-pointer NIL)) (arg1 (ffi:c-pointer NIL)) (arg2 (ffi:c-pointer NIL))) (:return-type NIL))) (y ffi:int)) (:return-type ffi:int) (:library +library-name+)) (ffi:def-call-out func123 (:name "func123") (:arguments (x (ffi:c-pointer div_t)) (z (ffi:c-ptr (ffi:c-array (ffi:c-ptr (ffi:c-ptr ffi:int)) 100))) (y (ffi:c-ptr (ffi:c-ptr (ffi:c-array ffi:int (1000 10)))))) (:return-type ffi:int) (:library +library-name+)) (ffi:def-call-out lispsort_double (:name "lispsort_double") (:arguments (n ffi:int) (array (ffi:c-ptr DOUBLE-FLOAT))) (:return-type NIL) (:library +library-name+)) (ffi:def-call-out test123 (:name "test") (:arguments (x SINGLE-FLOAT) (y DOUBLE-FLOAT)) (:return-type NIL) (:library +library-name+)) The module also handles strutcures and #define constants as shown below. SWIG automatically adds the constructors and accessors created for the struct to the list of symbols exported by the package. struct bar { short x, y; char a, b; int *z[1000]; struct bar * n; }; #define max 1000 (ffi:def-c-struct bar (x :type ffi:short) (y :type ffi:short) (a :type character) (b :type character) (z :type (ffi:c-array (ffi:c-ptr ffi:int) 1000)) (n :type (ffi:c-pointer bar))) (defconstant max 1000) 22.4 UFFI23 SWIG and LuaLua is an extension programming language designed to support general procedural programming with data description facilities. It also offers good support for object-oriented programming, functional programming, and data-driven programming. Lua is intended to be used as a powerful, light-weight configuration language for any program that needs one. Lua is implemented as a library, written in clean C (that is, in the common subset of ANSI C and C++). Its also a really tiny language, less than 6000 lines of code, which compiles to <100 kilobytes of binary code. It can be found at http://www.lua.org 23.1 PreliminariesThe current SWIG implementation is designed to work with Lua 5.0.x and Lua 5.1.x. It should work with later versions of Lua, but certainly not with Lua 4.0 due to substantial API changes. ((Currently SWIG generated code has only been tested on Windows with MingW, though given the nature of Lua, is should not have problems on other OS's)). It is possible to either static link or dynamic link a Lua module into the interpreter (normally Lua static links its libraries, as dynamic linking is not available on all platforms). 23.2 Running SWIGSuppose that you defined a SWIG module such as the following: %module example %{ #include "example.h" %} int gcd(int x, int y); extern double Foo;
To build a Lua module, run SWIG using the $ swig -lua example.i
If building a C++ extension, add the $ swig -c++ -lua example.i
This creates a C/C++ source file
The name of the wrapper file is derived from the name of the input file. For example, if the input file is 23.2.1 Compiling and Linking and Interpreter
Normally Lua is embedded into another program and will be statically linked. An extremely simple stand-alone interpreter ( #include <stdio.h> #include "lua.h" #include "lualib.h" #include "lauxlib.h" extern int luaopen_example(lua_State* L); // declare the wrapped module int main(int argc,char* argv[]) { lua_State *L; if (argc<2) { printf("%s: <filename.lua>\n",argv[0]); return 0; } L=lua_open(); luaopen_base(L); // load basic libs (eg. print) luaopen_example(L); // load the wrappered module if (luaL_loadfile(L,argv[1])==0) // load and run the file lua_pcall(L,0,0,0); else printf("unable to load %s\n",argv[1]); lua_close(L); return 0; }
A much improved set of code can be found in the Lua distribution The exact commands for compiling and linking vary from platform to platform. Here is a possible set of commands of doing this: $ swig -lua example.i -o example_wrap.c $ gcc -I/usr/include/lua -c min.c -o min.o $ gcc -I/usr/include/lua -c example_wrap.c -o example_wrap.o $ gcc -c example.c -o example.o $ gcc -I/usr/include/lua -L/usr/lib/lua min.o example_wrap.o example.o -o my_lua 23.2.2 Compiling a dynamic moduleMost, but not all platforms support the dynamic loading of modules (Windows & Linux do). Refer to the Lua manual to determine if your platform supports it. For compiling a dynamically loaded module the same wrapper can be used. The commands will be something like this: $ swig -lua example.i -o example_wrap.c $ gcc -I/usr/include/lua -c example_wrap.c -o example_wrap.o $ gcc -c example.c -o example.o $ gcc -shared -I/usr/include/lua -L/usr/lib/lua example_wrap.o example.o -o example.so The wrappers produced by SWIG can be compiled and linked with Lua 5.1.x. The loading is extremely simple. require("example") For those using Lua 5.0.x, you will also need an interpreter with the loadlib function (such as the default interpreter compiled with Lua). In order to dynamically load a module you must call the loadlib function with two parameters: the filename of the shared library, and the function exported by SWIG. Calling loadlib should return the function, which you then call to initialise the module my_init=loadlib("example.so","luaopen_example") -- for Unix/Linux --my_init=loadlib("example.dll","luaopen_example") -- for Windows assert(my_init) -- name sure its not nil my_init() -- call the init fn of the lib Or can be done in a single line of Lua code assert(loadlib("example.so","luaopen_example"))() If the code didn't work, don't panic. The best thing to do is to copy the module and your interpreter into a single directory and then execute the interpreter and try to manually load the module (take care, all this code is case sensitive). a,b,c=package.loadlib("example.so","luaopen_example") -- for Unix/Linux --a,b,c=package.loadlib("example.dll","luaopen_example") -- for Windows print(a,b,c)
Note: for Lua 5.0: if 'a' is a function, this its all working fine, all you need to do is call it a() to load your library which will add a table 'example' with all the functions added.
If it doesn't work, look at the error messages, in particular mesage 'b' 23.2.3 Using your moduleAssuming all goes well, you will be able to this: $ ./my_lua > print(example.gcd(4,6)) 2 > print(example.Foo) 3 > example.Foo=4 > print(example.Foo) 4 > 23.3 A tour of basic C/C++ wrappingBy default, SWIG tries to build a very natural Lua interface to your C/C++ code. This section briefly covers the essential aspects of this wrapping. 23.3.1 ModulesThe SWIG module directive specifies the name of the Lua module. If you specify `module example', then everything is wrapped into a Lua table 'example' containing all the functions and variables. When choosing a module name, make sure you don't use the same name as a built-in Lua command or standard module name. 23.3.2 FunctionsGlobal functions are wrapped as new Lua built-in functions. For example, %module example int fact(int n);
creates a built-in function > print example.fact(4) 24 > To avoid name collisions, SWIG create a Lua table which it keeps all the functions and global variables in. It is possible to copy the functions out of this and into the global environment with the following code. This can easily overwrite existing functions, so this must be used with care. > for k,v in pairs(example) do _G[k]=v end > print(fact(4)) 24 > It is also possible to rename the module with an assignment. > e=example > print(e.fact(4)) 24 > print(example.fact(4)) 24 23.3.3 Global variablesGlobal variables (which are linked to C code) are supported, and appear to be just another variable in Lua. However the actual mechanism is more complex. Given a global variable: %module example extern double Foo;
SWIG will effectively generate two functions > print(example.Foo) 3 > c=example.Foo -- c is a COPY of example.Foo, not the same thing > example.Foo=4 > print(c) 3 > c=5 -- this will not effect the original example.Foo > print(example.Foo,c) 4 5 Its is therefore not possible to 'move' the global variable into the global namespace as it is with functions. It is however, possible to rename the module with an assignment, to make it more convenient. > e=example > -- e and example are the same table > -- so e.Foo and example.Foo are the same thing > example.Foo=4 > print(e.Foo) 4 If a variable is marked with the %immutable directive then any attempts to set this variable will cause an Lua error. Given a global variable: %module example %immutable; extern double Foo; %mutable;
SWIG will allow the the reading of > print(e.Foo) -- reading works ok 4 > example.Foo=40 -- but writing does not This variable is immutable stack traceback: [C]: ? [C]: ? stdin:1: in main chunk [C]: ?
For those people who would rather that SWIG silently ignore the setting of immutables (as previous versions of the Lua bindings did), adding a Unlike earlier versions of the binding, it is now possible to add new functions or variables to the module, just as if it were a normal table. This also allows the user to rename/remove existing functions and constants (but not linked variables, mutable or immutable). Therefore users are recommended to be careful when doing so. > -- example.PI does not exist > print(example.PI) nil > example.PI=3.142 -- new value added > print(example.PI) 3.142 23.3.4 Constants and enumsBecause Lua doesn't really have the concept of constants, C/C++ constants are not really constant in Lua. They are actually just a copy of the value into the Lua interpreter. Therefore they can be changed just as any other value. For example given some constants: %module example %constant int ICONST=42; #define SCONST "Hello World" enum Days{SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY}; This is 'effectively' converted into the following Lua code: example.ICONST=42 example.SCONST="Hello World" example.SUNDAY=0 .... Constants are not guaranteed to remain constant in Lua. The name of the constant could be accidentally reassigned to refer to some other object. Unfortunately, there is no easy way for SWIG to generate code that prevents this. You will just have to be careful. 23.3.5 PointersC/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the <file.h> interface: %module example FILE *fopen(const char *filename, const char *mode); int fputs(const char *, FILE *); int fclose(FILE *); When wrapped, you will be able to use the functions in a natural way from Lua. For example: > f=example.fopen("junk","w") > example.fputs("Hello World",f) > example.fclose(f)
Unlike many scripting languages, Lua has had support for pointers to C/C++ object built in for a long time. They are called 'userdata'. Unlike many other SWIG versions which use some kind of encoded character string, all objects will be represented as a userdata. The SWIG-Lua bindings provides a special function > print(f) userdata: 003FDA80 > print(swig_type(f)) FILE * -- its a FILE* Lua enforces the integrity of its userdata, so it is virtually impossible to corrupt the data. But as the user of the pointer, you are responsible for freeing it, or closing any resources associated with it (just as you would in a C program). This does not apply so strictly to classes & structs (see below). One final note: if a function returns a NULL pointer, this is not encoded as a userdata, but as a Lua nil. > f=example.fopen("not there","r") -- this will return a NULL in C > print(f) nil 23.3.6 StructuresIf you wrap a C structure, it is also mapped to a Lua userdata. By adding a metatable to the userdata, this provides a very natural interface. For example, struct Point{ int x,y; }; is used as follows: > p=example.new_Point() > p.x=3 > p.y=5 > print(p.x,p.y) 3 5 >
Similar access is provided for unions and the data members of C++ classes. If you print out the value of p in the above example, you will see something like this: > print(p) userdata: 003FA320 Like the pointer in the previous section, this is held as a userdata. However, additional features have been added to make this more usable. SWIG effectivly creates some accessor/mutator functions to get and set the data. These functions will be added to the userdata's metatable. This provides the natural access to the member variables that were shown above (see end of the document for full details).
struct Foo { ... %immutable; int x; // Read-only members char *name; %mutable; ... }; The mechanism for managing char* members as well as array members is similar to other languages. It is somewhat cumbersome and should probably be better handled by defining of typemaps (described later). 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: struct Foo { int a; }; struct Bar { Foo f; }; Now, suppose that you access the f attribute of Bar like this: > b = Bar() > x = b.f In this case, x is a pointer that points to the Foo that is inside b. This is the same value as generated by this C code: Bar b; Foo *x = &b->f; // Points inside b Because the pointer points inside the structure, you can modify the contents and everything works just like you would expect. For example: > b = Bar() > b.f.a = 3 -- Modify attribute of structure member > x = b.f > x.a = 3 -- Modifies the same structure 23.3.7 C++ classesC++ classes are wrapped by a Lua userdata as well. For example, if you have this class, class List { public: List(); ~List(); int search(char *item); void insert(char *item); void remove(char *item); char *get(int n); int length; }; you can use it in Lua like this: > l = example.List() > l:insert("Ale") > l:insert("Stout") > l:insert("Lager") > print(l:get(1)) Stout > print(l:length) 3 >
(Note: for calling methods of a class, you use Class data members are accessed in the same manner as C structures. Static class members present a special problem for Lua, as Lua doesn't have support for such features. Therefore, SWIG generates wrappers that try to work around some of these issues. To illustrate, suppose you have a class like this: class Spam { public: static void foo(); static int bar; }; In Lua, the static members can be accessed as follows: > example.Spam_foo() -- calling Spam::foo() > a=example.Spam_bar -- reading Spam::bar > example.Spam_bar=b -- writing to Spam::bar It is not (currently) possible to access static members of an instance: > s=example.Spam() -- s is a Spam instance > s.foo() -- Spam::foo() via an instance -- does NOT work 23.3.8 C++ inheritanceSWIG is fully aware of issues related to C++ inheritance. Therefore, if you have classes like this class Foo { ... }; class Bar : public Foo { ... }; And if you have functions like this void spam(Foo *f);
then the function It is safe to use multiple inheritance with SWIG. 23.3.9 Pointers, references, values, and arraysIn C++, there are many different ways a function might receive and manipulate objects. For example: 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 In SWIG, there is no detailed distinction like this–specifically, there are only “objects”. There are no pointers, references, arrays, and so forth. 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: > f = Foo() -- Create a Foo > spam1(f) -- Ok. Pointer > spam2(f) -- Ok. Reference > spam3(f) -- Ok. Value. > spam4(f) -- Ok. Array (1 element) Similar behaviour occurs for return values. For example, if you had functions like this, Foo *spam5(); Foo &spam6(); Foo spam7(); then all three functions will return a pointer to some Foo object. Since the third function (spam7) returns a value, newly allocated memory is used to hold the result and a pointer is returned (Lua will release this memory when the return value is garbage collected). The other two are pointers which are assumed to be managed by the C code and so will not be garbage collected. 23.3.10 C++ overloaded functionsC++ overloaded functions, methods, and constructors are mostly supported by SWIG. For example, if you have two functions like this: void foo(int); void foo(char *c); You can use them in Lua in a straightforward manner: > foo(3) -- foo(int) > foo("Hello") -- foo(char *c) However due to Lua's coercion mechanism is can sometimes do strange things. > foo("3") -- "3" can be coerced into an int, so it calls foo(int)! As this coercion mechanism is an integral part of Lua, there is no easy way to get around this other than renaming of functions (see below). Similarly, if you have a class like this, class Foo { public: Foo(); Foo(const Foo &); ... }; you can write Lua code like this: > f = Foo() -- Create a Foo > g = Foo(f) -- Copy f Overloading support is not quite as flexible as in C++. Sometimes there are methods that SWIG can't disambiguate. For example: void spam(int); void spam(short); or VOID FOO(bAR *B); void foo(Bar &b); If declarations such as these appear, you will get a warning message like this: example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int) at example.i:11. To fix this, you either need to ignore or rename one of the methods. For example: %rename(spam_short) spam(short); ... void spam(int); void spam(short); // Accessed as spam_short or %ignore spam(short); ... void spam(int); void spam(short); // Ignored 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. Please refer to the “SWIG and C++” chapter for more information about overloading. Dealing with the Lua coercion mechanism, the priority is roughly (integers, floats, strings, userdata). But it is better to rename the functions rather than rely upon the ordering. 23.3.11 C++ operatorsCertain C++ overloaded operators can be handled automatically by SWIG. For example, consider a class like this: 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; } }; When wrapped, it works like you expect: > c = Complex(3,4) > d = Complex(7,8) > e = c + d > e:re() 10.0 > e:im() 12.0 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 class Complex { ... friend Complex operator+(double, const Complex &c); ... }; 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: %rename(Complex_add_dc) operator+(double, const Complex &); ... Complex operator+(double, const Complex &c);
There are ways to make this operator appear as part of the class using the
Also, be aware that certain operators don't map cleanly to Lua, and some Lua operators don't map cleanly to C++ operators. For instance, overloaded assignment operators don't map to Lua semantics and will be ignored, and C++ doesn't support Lua's concatenation operator ( In order to keep maximum compatibility within the different languages in SWIG, the Lua bindings uses the same set of operator names as python. Although internally it renames the functions to something else (on order to work with Lua). The current list of operators which can be overloaded (and the alternative function names) are:
Note: in Lua, only the equals, less than, and less than equals operators are defined. The other operators (!=,>,> are achieved by using a logical not applied to the results of other operators. The following operators cannot be overloaded (mainly because they are not supported in Lua)
SWIG also accepts the const char* __str__() { static char buffer[255]; sprintf(buffer,"Complex(%g,%g)",this->re(),this->im()); return buffer; } Then this will support the following code in Lua > c = Complex(3,4) > d = Complex(7,8) > e = c + d > print(e) Complex(10,12) > s=tostring(e) -- s is the number in string form > print(s) Complex(10,12)
It is also possible to overload the operator class Complex { //.... double __getitem__(int i)const; // i is the index, returns the data void __setitem__(int i,double d); // i is the index, d is the data }; 23.3.12 Class extension with %extendOne of the more interesting features of SWIG is that it can extend structures and classes with new methods. In the previous section, the Complex class would have benefited greatly from an __str__() method as well as some repairs to the operator overloading. It can also be used to add additional functions to the class if they are needed. Take the original Complex class 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; } }; Now we extend it with some new code %extend Complex { const char *__str__() { static char tmp[1024]; sprintf(tmp,"Complex(%g,%g)", $self->re(),$self->im()); return tmp; } bool operator==(const Complex& c) { return ($self->re()==c.re() && $self->im()==c.im();} }; Now, in Lua > c = Complex(3,4) > d = Complex(7,8) > e = c + d > print(e) -- print uses __str__ to get the string form to print Complex(10,12) > print(e==Complex(10,12)) -- testing the == operator true > print(e!=Complex(12,12)) -- the != uses the == operator true Extend works with both C and C++ code, on classes and structs. It does not modify the underlying object in any way—the extensions only show up in the Lua interface. The only item to take note of is the code has to use the '$self' instead of 'this', and that you cannot access protected/private members of the code (as you are not officially part of the class). 23.3.13 C++ templatesC++ 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 template directive. For example: %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>; In Lua: > p = example.pairii(3,4) > print(p.first,p.second) 3 4 Obviously, there is more to template wrapping than shown in this example. More details can be found in the SWIG and C++ chapter. Some more complicated examples will appear later. 23.3.14 C++ Smart PointersIn 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 operator→() like this: template<class T> class SmartPtr { ... T *operator->(); ... } Then, if you have a class like this, class Foo { public: int x; int bar(); }; A smart pointer would be used in C++ as follows: SmartPtr<Foo> p = CreateFoo(); // Created somehow (not shown) ... p->x = 3; // Foo::x int y = p->bar(); // Foo::bar To wrap this, simply tell SWIG about the SmartPtr class and the low-level Foo object. Make sure you instantiate SmartPtr using template if necessary. For example: %module example ... %template(SmartPtrFoo) SmartPtr<Foo>; ... Now, in Lua, everything should just “work”: > p = example.CreateFoo() -- Create a smart-pointer somehow > p.x = 3 -- Foo::x > print(p:bar()) -- Foo::bar
If you ever need to access the underlying pointer returned by > f = p:__deref__() -- Returns underlying Foo * 23.3.15 C++ ExceptionsLua does not natively support exceptions, but it has errors which are similar. When a Lua function terminates with an error it returns one value back to the caller. SWIG automatically maps any basic type which is thrown into a Lua error. Therefore for a function: int message() throw(const char *) { throw("I died."); return 1; } SWIG will automatically convert this to a Lua error. > message() I died. stack traceback: [C]: in function 'message' stdin:1: in main chunk [C]: ? > If you want to catch an exception, you must use either pcall() or xpcall(), which are documented in the Lua manual. Using xpcall will allow you to obtain additional debug information (such as a stacktrace). > function a() b() end -- function a() calls function b() > function b() message() end -- function b() calls C++ function message(), which throws > ok,res=pcall(a) -- call the function > print(ok,res) false I died. > ok,res=xpcall(a,debug.traceback) -- call the function > print(ok,res) false I died. stack traceback: [C]: in function 'message' runme.lua:70: in function 'b' runme.lua:67: in function <runme.lua:66> [C]: in function 'xpcall' runme.lua:95: in main chunk [C]: ? SWIG is able to throw numeric types, enums, chars, char*'s and std::string's without problem. It has also written typemaps for std::exception and its derived classes, which convert the exception into and error string. However its not so simple for to throw other types of objects. Thrown objects are not valid outside the 'catch' block. Therefore they cannot be returned to the interpreter. The obvious ways to overcome this would be to either return a copy of the object, or so convert the object to a string and return that. Though it seems obvious to perform the former, in some cases this is not possible, most notably when SWIG has no information about the object, or the object is not copyable/creatable. Therefore by default SWIG converts all thrown object into strings and returns them. So given a function: void throw_A() throw(A*) { throw new A(); } SWIG will just convert it (poorly) to a string and use that as its error. (Yes its not that useful, but it always works). > throw_A() object exception:A * stack traceback: [C]: in function 'unknown' stdin:1: in main chunk [C]: ? > To get a more useful behaviour out of SWIG you must either: provide a way to convert your exceptions into strings, or throw objects which can be copied. If you have your own class which you want output as a string you will need to add a typemap something like this: %typemap(throws) my_except %{ lua_pushstring(L,$1.what()); // assuming my_except::what() returns a const char* message SWIG_fail; // trigger the error handler %}
If you wish your exception to be returned to the interpreter, it must firstly be copyable. Then you must have and additional %apply SWIGTYPE EXCEPTION_BY_VAL {Exc}; // tell SWIG to return Exc by value to interpreter class Exc { public: Exc(int c, const char *m) { code = c; strncpy(msg,m,256); } int code; char msg[256]; }; void throw_exc() throw(Exc) { throw(Exc(42,"Hosed")); } Then the following code can be used (note: we use pcall to catch the error so we can process the exception). > ok,res=pcall(throw_exc) > print(ok) false > print(res) userdata: 0003D880 > print(res.code,res.msg) 42 Hosed > Note: is is also possible (though tedious) to have a function throw several different kinds of exceptions. To process this will require a pcall, followed by a set of if statements checking the type of the error. All of this code assumes that your C++ code uses exception specification (which a lot doesn't). If it doesn't consult the “Exception handling with %catches” section and the “ Exception handling with %exception” section, for more details on how to add exception specification to functions or globally (respectively). 23.4 TypemapsThis section explains what typemaps are and the usage of them. The default wrappering behaviour of SWIG is enough in most cases. However sometimes SWIG may need a little additional assistance to know which typemap to apply to provide the best wrappering. This section will be explaining how to use typemaps to best effect 23.4.1 What is a typemap?A typemap is nothing more than a code generation rule that is attached to a specific C datatype. For example, to convert integers from Lua to C, you might define a typemap like this: %module example %typemap(in) int { $1 = (int) lua_tonumber(L,$input); printf("Received an integer : %d\n",$1); } %inline %{ extern int fact(int n); %} Note: you shouldn't use this typemap, as SWIG already has a typemap for this task. This is purely for example. 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 int 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 $ are used. The $1 variable is placeholder for a local variable of type int. The $input is the index on the Lua stack for the value to be used. When this example is compiled into a Lua module, it operates as follows: > require "example" > print(example.fact(6)) Received an integer : 6 720 23.4.2 Using typemapsThere are many ready written typemaps built into SWIG for all common types (int, float, short, long, char*, enum and more), which SWIG uses automatically, with no effort required on your part. However for more complex functions which use input/output parameters or arrays, you will need to make use of <typemaps.i>, which contains typemaps for these situations. For example, consider these functions: void add(int x, int y, int *result) { *result = x + y; } int sub(int *x1, int *y1) { return *x1-*y1; } void swap(int *sx, int *sy) { int t=*sx; *sx=*sy; *sy=t; } It is clear to the programmer, that 'result' is an output parameter, 'x1' and 'y1' are input parameters and 'sx' and 'sy' are input/output parameters. However is not apparent to SWIG, so SWIG must to informed about which kind they are, so it can wrapper accordingly.
One means would be to rename the argument name to help SWIG, eg %include <typemaps.i> %apply int* OUTPUT {int *result}; // int *result is output %apply int* INPUT {int *x1, int *y1}; // int *x1 and int *y1 are input %apply int* INOUT {int *sx, int *sy}; // int *sx and int *sy are input and output void add(int x, int y, int *result); int sub(int *x1, int *y1); void swap(int *sx, int *sy); When wrapped, it gives the following results: > require "example" > print(example.add(1,2)) 3 > print(demo.sub(1,2)) -1 > a,b=1,2 > c,d=demo.swap(a,b) > print(a,b,c,d) 1 2 2 1 Notice, that 'result' is not required in the arguments to call the function, as it an output parameter only. For 'sx' and 'sy' they must be passed in (as they are input), but the original value is not modified (Lua does not have a pass by reference feature). The modified results are then returned as two return values. All INPUT/OUTPUT/INOUT arguments will behave in a similar manner.
Note: C++ references must be handled exactly the same way. However SWIG will automatically wrap a 23.4.3 Typemaps and arraysArrays present a challenge for SWIG, because like pointers SWIG does not know whether these are input or output values, nor does SWIG have any indication of how large an array should be. However with the proper guidance SWIG can easily wrapper arrays for convenient usage. Given the functions: extern void sort_int(int* arr, int len); extern void sort_double(double* arr, int len);
There are basically two ways that SWIG can deal with this. The first way, uses the
The second and more intuitive way, would be to pass a Lua table directly into the function, and have SWIG automatically convert between Lua-table and C-array. Within the The wrapper file below, shows both the use of carrays as well as the use of the typemap to wrap arrays. // using the C-array %include <carrays.i> // this declares a batch of function for manipulating C integer arrays %array_functions(int,int) extern void sort_int(int* arr, int len); // the function to wrap // using typemaps %include <typemaps.i> %apply (double *INOUT,int) {(double* arr,int len)}; extern void sort_double(double* arr, int len); // the function to wrap Once wrappered, the functions can both be called, though with different ease of use: require "example" ARRAY_SIZE=10 -- passing a C array to the sort_int() arr=example.new_int(ARRAY_SIZE) -- create the array for i=0,ARRAY_SIZE-1 do -- index 0..9 (just like C) example.int_setitem(arr,i,math.random(1000)) end example.sort_int(arr,ARRAY_SIZE) -- call the function example.delete_int(arr) -- must delete the allocated memory -- use a typemap to call with a Lua-table -- one item of note: the typemap creates a copy, rather than edit-in-place t={} -- a Lua table for i=1,ARRAY_SIZE do -- index 1..10 (Lua style) t[i]=math.random(1000)/10 end t=example.sort_double(t) -- replace t with the result
Obviously the first version could be made less tedious by writing a Lua function to perform the conversion from a table to a C-array. The Warning: in C indexes start at ZERO, in Lua indexes start at ONE. SWIG expects C-arrays to be filled for 0..N-1 and Lua tables to be 1..N, (the indexing follows the norm for the language). In the typemap when it converts the table to an array it quietly changes the indexing accordingly. Take note of this behaviour if you have a C function which returns indexes. Note: SWIG also can support arrays of pointers in a similar manner. 23.4.4 Typemaps and pointer-pointer functionsSeveral C++ libraries use a pointer-pointer functions to create its objects. These functions require a pointer to a pointer which is then filled with the pointer to the new object. Microsoft's COM and DirectX as well as many other libraries have this kind of function. An example is given below: struct iMath; // some structure int Create_Math(iMath** pptr); // its creator (assume it mallocs) Which would be used with the following C code: iMath* ptr; int ok; ok=Create_Math(&ptr); // do things with ptr //... free(ptr); // dispose of iMath SWIG has a ready written typemap to deal with such a kind of function in <typemaps.i>. It provides the correct wrappering as well as setting the flag to inform Lua that the object in question should be garbage collected. Therefore the code is simply: %include <typemaps.i> %apply SWIGTYPE** OUTPUT{iMath **pptr }; // tell SWIG its an output struct iMath; // some structure int Create_Math(iMath** pptr); // its creator (assume it mallocs) The usage is as follows: ok,ptr=Create_Math() -- ptr is a iMath* which is returned with the int (ok) ptr=nil -- the iMath* will be GC'ed as normal 23.5 Writing typemaps
This section describes how you can modify SWIG's default wrapping behavior for various C/C++ datatypes using the Before proceeding, it should be stressed that writing typemaps is rarely needed unless you want to change some aspect of the wrappering, or to achieve an effect which in not available with the default bindings. Before proceeding, you should read the previous section on using typemaps, as well as read the ready written typemaps found in luatypemaps.swg and typemaps.i. These are both well documented and fairly easy to read. You should not attempt to write your own typemaps until you have read and can understand both of these files (they may well also give you a idea to base your worn on). 23.5.1 Typemaps you can writeThere are many different types of typemap that can be written, the full list can be found in the “Typemaps” chapter. However the following are the most commonly used ones.
23.5.2 SWIG's Lua-C APIThis section explains the SWIG specific Lua-C API. It does not cover the main Lua-C api, as this is well documented and not worth covering.
This is the standard function used for converting a Lua userdata to a void*. It takes the value at the given index in the Lua state and converts it to a userdata. It will then provide the neccesary type checks, confirming that the pointer is compatible with the type given in 'type'. Then finally setting '*ptr' to the pointer. If flags is set to SWIG_POINTER_DISOWN, this is will clear any ownership flag set on the object.
This is the opposite of SWIG_ConvertPtr, as it pushes a new userdata which wrappers the pointer 'ptr' of type 'type'. The parameter 'own' specifies if the object is owned be Lua and if it is 1 then Lua will GC the object when the userdata is disposed of.
This function is a version of SWIG_ConvertPtr(), except that it will either work, or it will trigger a lua_error() with a text error message. This function is rarely used, and may be deprecated in the future.
This macro, when called within the context of a SWIG wrappered function, will jump to the error handler code. This will call any cleanup code (freeing any temp variables) and then triggers a lua_error. if (!SWIG_IsOK(SWIG_ConvertPtr( .....)){ lua_pushstring(L,"something bad happened"); SWIG_fail; }
This macro, when called within the context of a SWIG wrappered function, will display the error message and jump to the error handler code. The error message is of the form "Error in func_name (arg argnum), expected 'type' got 'whatever the type was'"
Similar to SWIG_fail_arg, except that it will display the swig_type_info information instead. 23.6 Customization of your BindingsThis section covers adding of some small extra bits to your module to add the last finishing touches. 23.6.1 Writing your own custom wrappers
Sometimes, it may be neccesary to add your own special functions, which bypass the normal SWIG wrappering method, and just use the native Lua API calls. These 'native' functions allow direct adding of your own code into the module. This is performed with the %native(my_func) int native_function(lua_State*L); // registers native_function() with SWIG ... %{ int native_function(lua_State*L) // my native code { ... } %}
The 23.6.2 Adding additional Lua codeAs well as adding additional C/C++ code, its also possible to add your own Lua code to the module as well. This code is executed once all other initialisation, including the %init code has been called.
The directive %module example; %luacode { function example.greet() print "hello world" end print "Module loaded ok" } ... %} Notice that the code is not part of the module table. Therefore any references to the module must have the module name added.
Should there be an error in the Lua code, this will not stop loading of the module. The default behaviour of SWIG is to print a error message to stderr and then continue. It is possible to change this behaviour by using a Good uses for this feature is adding of new code, or writing helper functions to simplify some of the code. See Examples/lua/arrays for an example of this code. 23.7 Details on the Lua bindingIn the previous section, a high-level view of Lua wrapping was presented. Obviously a lot of stuff happens behind the scenes to make this happen. This section will explain some of the low-level details on how this is achieved. If you just want to use SWIG and don't care how it works, then stop reading here. This is going into the guts of the code and how it works. Its mainly for people who need to know whats going on within the code. 23.7.1 Binding global data into the module.Assuming that you had some global data that you wanted to share between C and Lua. How does SWIG do it? %module example; extern double Foo; SWIG will effectively generate the pair of functions void Foo_set(double); double Foo_get();
At initialisation time, it will then add to the interpreter a table called 'example', which represents the module. It will then add all its functions to the module. (Note: older versions of SWIG actually added the Foo_set() and Foo_get() functions, current implementation does not add these functions any more.) But it also adds a metatable to this table, which has two functions ( > print(example) table: 003F8F90 > m=getmetatable(example) > table.foreach(m,print) .set table: 003F9088 .get table: 003F9038 __index function: 003F8FE0 __newindex function: 003F8FF8 > g=m['.get'] > table.foreach(g,print) Foo function: 003FAFD8 > The .get and .set tables are lookups connecting the variable name 'Foo' to the accessor/mutator functions (Foo_set,Foo_get)
The Lua equivalent of the code for the function __index(mod,name) local g=getmetatable(mod)['.get'] -- gets the table if not g then return nil end local f=g[name] -- looks for the function -- calls it & returns the value if type(f)=="function" then return f() end return nil end function __newindex(mod,name,value) local s=getmetatable(mod)['.set'] -- gets the table if not s then return end local f=s[name] -- looks for the function -- calls it to set the value if type(f)=="function" then f(value) else rawset(mod,name,value) end end
That way when you call 23.7.2 Userdata and MetatablesAs mentioned earlier, classes and structures, are all held as pointer, using the Lua 'userdata' structure. This structure is actually a pointer to a C structure 'swig_lua_userdata', which contains the pointer to the data, a pointer to the swig_type_info (an internal SWIG struct) and a flag which marks if the object is to be disposed of when the interpreter no longer needs it. The actual accessing of the object is done via the metatable attached to this userdata. The metatable is a Lua 5.0 feature (which is also why SWIG cannot wrap Lua 4.0). Its a table which holds a list of functions, operators and attributes. This is what gives the userdata the feeling that it is a real object and not just a hunk of memory. Given a class %module excpp; class Point { public: int x,y; Point(){x=y=0;} ~Point(){} virtual void Print(){printf("Point @%p (%d,%d)\n",this,x,y);} }; SWIG will create a module excpp, with all the various function inside. However to allow the intuitive use of the userdata is also creates up a set of metatables. As seen in the above section on global variables, use of the metatables allows for wrappers to be used intuitively. To save effort, the code creates one metatable per class and stores it inside Lua's registry. Then when an new object is instantiated, the metatable is found in the registry and the userdata associated to the metatable. Currently derived classes make a complete copy of the base classes table and then add on their own additional function. Some of the internals can be seen by looking at a classes metatable. > p=excpp.Point() > print(p) userdata: 003FDB28 > m=getmetatable(p) > table.foreach(m,print) .type Point __gc function: 003FB6C8 __newindex function: 003FB6B0 __index function: 003FB698 .get table: 003FB4D8 .set table: 003FB500 .fn table: 003FB528 The '.type' attribute is the name of the class. The '.get' and '.set' tables work in a similar manner to the modules, the main difference is the '.fn' table which also holds all the member functions. (The '__gc' function is the classes destructor function) The Lua equivalent of the code for enabling functions looks a little like this function __index(obj,name) local m=getmetatable(obj) -- gets the metatable if not m then return nil end local g=m['.get'] -- gets the attribute table if not g then return nil end local f=g[name] -- looks for the get_attribute function -- calls it & returns the value if type(f)=="function" then return f() end -- ok, so it not an attribute, maybe its a function local fn=m['.fn'] -- gets the function table if not fn then return nil end local f=fn[name] -- looks for the function -- if found the fn then return the function -- so the interpreter can call it if type(f)=="function" then return f end return nil end So when 'p:Print()' is called, the __index looks on the object metatable for a 'Print' attribute, then looks for a 'Print' function. When it finds the function, it returns the function, and then interpreter can call 'Point_Print(p)' In theory, you can play with this usertable & add new features, but remember that it is a shared table between all instances of one class, and you could very easily corrupt the functions in all the instances. Note: Both the opaque structures (like the FILE*) and normal wrappered classes/structs use the same 'swig_lua_userdata' structure. Though the opaque structures has do not have a metatable attached, or any information on how to dispose of them when the interpreter has finished with them. Note: Operator overloads are basically done in the same way, by adding functions such as '__add' & '__call' to the classes metatable. The current implementation is a bit rough as it will add any member function beginning with '__' into the metatable too, assuming its an operator overload. 23.7.3 Memory management
Lua is very helpful with the memory management. The 'swig_lua_userdata' is fully managed by the interpreter itself. This means that neither the C code nor the Lua code can damage it. Once a piece of userdata has no references to it, it is not instantly collected, but will be collected when Lua deems is necessary. (You can force collection by calling the Lua function It is currently not recommended to edit this field or add some user code, to change the behaviour. Though for those who wish to try, here is where to look. It is also currently not possible to change the ownership flag on the data (unlike most other scripting languages, Lua does not permit access to the data from within the interpreter) 24 SWIG and Modula-3This chapter describes SWIG's support of Modula-3. You should be familiar with the basics of SWIG, especially typemaps. 24.1 OverviewThe Modula-3 support is very basic and highly experimental! Many features are still not designed satisfyingly and I need more discussion about the odds and ends. Don't rely on any feature, incompatible changes are likely in the future! The Modula-3 generator was already useful for interfacing to the libraries
I took some more time to explain why I think it's right what I'm doing. So the introduction got a bit longer than it should … 24.1.1 Why not scripting ?SWIG started as wrapper from the fast compiled languages C and C++ to high level scripting languages like Python. Although scripting languages are designed to make programming life easier by hiding machine internals from the programmer there are several aspects of today's scripting languages that are unfavourable in my opinion. Besides C, C++, Cluster (a Modula derivate for Amiga computers) I evaluated several scripting like languages in the past: Different dialects of BASIC, Perl, ARexx (a variant of Rexx for Amiga computers), shell scripts. I found them too inconsistent, too weak in distinguishing types, too weak in encapsulating pieces of code. Eventually I have started several projects in Python because of the fine syntax. But when projects became larger I lost the track. I got convinced that one can not have maintainable code in a language that is not statically typed. In fact the main advantages of scripting languages e.g. matching regular expressions, complex built-in datatypes like lists, dictionaries, are not advantages of the language itself but can be provided by function libraries. 24.1.2 Why Modula-3 ?Modula-3 is a compiler language in the tradition of Niklaus Wirth's Modula 2, which is in turn a successor of the popular Pascal. I have chosen Modula-3 because of its logical syntax, strong modularization, the type system which is very detailed for machine types compared to other languages. Of course it supports all of the modern games like exceptions, objects, garbage collection, threads. While C++ programmers must control three languages, namely the preprocessor, C and ++, Modula-3 is made in one go and the language definition is really compact.
On the one hand Modula-3 can be safe (but probably less efficient) in normal modules while providing much static and dynamic safety. On the other hand you can write efficient but less safe code in the style of C within Unfortunately Modula's safety and strength requires more writing than scripting languages do. Today if I want to safe characters I prefer Haskell (similar to OCAML) - it's statically typed, too. 24.1.3 Why C / C++ ?Although it is no problem to write Modula-3 programs that performs as fast as C most libraries are not written in Modula-3 but in C. Fortunately the binary interface of most function libraries can be addressed by Modula-3. Even more fortunately even non-C libraries may provide C header files. This is where SWIG becomes helpful. 24.1.4 Why SWIG ?The C headers and the possibility to interface to C libraries still leaves the work for you to write Modula-3 interfaces to them. To make things comfortable you will also need wrappers that convert between high-level features of Modula-3 (garbage collecting, exceptions) and the low level of the C libraries.
SWIG converts C headers to Modula-3 interfaces for you. You could call the C functions without loss of efficiency but it won't be joy because you could not pass
But you have still a problem: C library interfaces are often ill. They lack for certain information because C compilers wouldn't care about. You should integrate detailed type information by adding Without SWIG you would probably never consider to call C++ libraries from Modula-3. But with SWIG this is worth a consideration. SWIG can write C wrappers to C++ functions and object methods that may throw exceptions. In fact it breaks down C++ libraries to C interfaces which can be in turn called from Modula-3. To make it complete you can hide the C interface with Modula-3 classes and exceptions. Although SWIG does the best it can do it can only serve as a one-way strategy. That means you can use C++ libraries with Modula-3 (even with call back functions), but it's certainly not possible to smoothly integrate Modula-3 code into a C / C++ project. 24.2 Conception24.2.1 Interfaces to C libraries
Modula-3 has an integrated support for calling C functions. This is also extensively used by the standard Modula-3 libraries to call OS functions. The Modula-3 part of SWIG and the corresponding SWIG library
In each run of SWIG the Modula-3 part generates several files:
Here's a scheme of how the function calls to Modula-3 wrappers are redirected to C library functions:
I have still no good conception how one can split C library interfaces into type oriented interfaces. A Module in Modula-3 represents an Abstract DataType (or call it a static classes, i.e. a class without virtual methods). E.g. if you have a principal type, say
The normal operation of SWIG is to generate a fixed set of files per call. To generate multiple modules one has to write one SWIG interface (different SWIG interfaces can share common data) per module. Identifiers belonging to a different module may ignored ( 24.2.2 Interfaces to C++ librariesInterfaces to C++ files are much more complicated and there are some more design decisions that are not made, yet. Modula-3 has no support for C++ functions but C++ compilers should support generating C++ functions with a C interface. Here's a scheme of how the function calls to Modula-3 wrappers a redirected to C library functions:
Wrapping C++ libraries arises additional problems:
Be warned: There is no C++ library I wrote a SWIG interface for, so I'm not sure if this is possible or sensible, yet. 24.3 Preliminaries24.3.1 Compilers
There are different Modula-3 compilers around: cm3, pm3, ezm3, Klagenfurth Modula-3, Cambridge Modula-3. SWIG itself does not contain compiler specific code but the library file 24.3.2 Additional Commandline OptionsThere are some experimental command line options that prevent SWIG from generating interface files. Instead files are emitted that may assist you when writing SWIG interface files.
24.4 Modula-3 typemaps24.4.1 Inputs and outputsEach C procedure has a bunch of inputs and outputs. Inputs are passed as function arguments, outputs are updated referential arguments and the function value.
Each C type can have several typemaps that apply only in case if a type is used for an input argument, for an output argument, or for a return value. A further typemap may specify the direction that is used for certain parameters. I have chosen this separation in order to be able to write general typemaps for the typemap library
The typemaps specific to Modula-3 have a common name scheme: A typemap name starts with “m3”, followed by “raw” or “wrap” depending on whether it controls the generation of the Module The main task of SWIG is to build wrapper function, i.e. functions that convert values between C and Modula-3 and call the corresponding C function. Modula-3 wrapper functions generated by SWIG consist of the following parts:
24.4.2 Subranges, Enumerations, SetsSubranges, enumerations, and sets are machine oriented types that make Modula very strong and expressive compared with the type systems of many other languages.
Using them extensively makes Modula code very safe and readable.
C supports enumerations, too, but they are not as safe as the ones of Modula. Thus they are abused for many things: For named choices, for integer constant definitions, for sets. To make it complete every way of defining a value in C (
I played around with several 24.4.3 Objects
Declarations of C++ classes are mapped to 24.4.4 Imports
Pieces of Modula-3 code provided by typemaps may contain identifiers from foreign modules. If the typemap
It is cumbersome to add this typemap to each piece of Modula-3 code. It is especially useful when writing general typemaps for the typemap library %insert(m3rawintf) %{ IMPORT M3toC; %} 24.4.5 ExceptionsModula-3 provides another possibility of an output of a function: exceptions. Any piece of Modula-3 code that SWIG inserts due to a typemap can raise an exception. This way you can also convert an error code from a C function into a Modula-3 exception.
The 24.4.6 ExampleThe generation of wrappers in Modula-3 needs very fine control to take advantage of the language features. Here is an example of a generated wrapper where almost everything is generated by a typemap: (* %relabel m3wrapinmode m3wrapinname m3wrapintype m3wrapindefault *) PROCEDURE Name (READONLY str : TEXT := "" ) (* m3wrapoutcheck:throws *) : NameResult RAISES {E} = CONST arg1name = "str"; (* m3wrapargconst *) VAR arg0 : C.char_star; (* m3wrapretvar *) arg1 : C.char_star; (* m3wrapargvar *) arg2 : C.int; result : RECORD (*m3wrapretname m3wraprettype*) unixPath : TEXT; (*m3wrapoutname m3wrapouttype*) checksum : CARDINAL; END; BEGIN TRY arg1 := M3toC.SharedTtoS(str); (* m3wrapinconv *) IF Text.Length(arg1) > 10 THEN (* m3wrapincheck *) RAISE E("str too long"); END; (* m3wrapretraw m3wrapargraw *) arg0 := MessyToUnix (arg1, arg2); result.unixPath := M3toC.CopyStoT(arg0); (* m3wrapretconv *) result.checksum := arg2; (* m3wrapoutconv *) IF result.checksum = 0 THEN (* m3wrapoutcheck *) RAISE E("invalid checksum"); END; FINALLY M3toC.FreeSharedS(str,arg1); (* m3wrapfreearg *) END; END Name; 24.5 More hints to the generator24.5.1 Features
24.5.2 Pragmas
24.6 Remarks
25 SWIG and MzSchemeThis section contains information on SWIG's support of MzScheme. 25.1 Creating native MzScheme structuresExample interface file: /* define a macro for the struct creation */ %define handle_ptr(TYPE,NAME) %typemap(argout) TYPE *NAME{ Scheme_Object *o = SWIG_NewStructFromPtr($1, $*1_mangle); SWIG_APPEND_VALUE(o); } %typemap(in,numinputs=0) TYPE *NAME (TYPE temp) { $1 = &temp; } %enddef /* setup the typemaps for the pointer to an output parameter cntrs */ handle_ptr(struct diag_cntrs, cntrs); Then in scheme, you can use regular struct access procedures like ; suppose a function created a struct foo as ; (define foo (make-diag-cntrs (#x1 #x2 #x3) (make-inspector)) ; Then you can do (format "0x~x" (diag-cntrs-field1 foo)) (format "0x~x" (diag-cntrs-field2 foo)) ;etc... That's pretty much it. It works with nested structs as well. 26 SWIG and OcamlThis chapter describes SWIG's support of Ocaml. Ocaml is a relatively recent addition to the ML family, and is a recent addition to SWIG. It's the second compiled, typed language to be added. Ocaml has widely acknowledged benefits for engineers, mostly derived from a sophisticated type system, compile-time checking which eliminates several classes of common programming errors, and good native performance. While all of this is wonderful, there are well-written C and C++ libraries that Ocaml users will want to take advantage of as part of their arsenal (such as SSL and gdbm), as well as their own mature C and C++ code. SWIG allows this code to be used in a natural, type-safe way with Ocaml, by providing the necessary, but repetitive glue code which creates and uses Ocaml values to communicate with C and C++ code. In addition, SWIG also produces the needed Ocaml source that binds variants, functions, classes, etc. If you're not familiar with the Objective Caml language, you can visit The Ocaml Website. 26.1 Preliminaries
SWIG 1.3 works with Ocaml 3.04 and above. Given the choice, you should use the latest stable release. The SWIG Ocaml module has been tested on Linux (x86,PPC,Sparc) and Cygwin on Windows. The best way to determine whether your system will work is to compile the examples and test-suite which come with SWIG. You can do this by running 26.1.1 Running SWIG
The basics of getting a SWIG Ocaml module up and running can be seen from one of SWIG's example Makefiles, but is also described here. To build an Ocaml module, run SWIG using the %swig -ocaml example.i
This will produce 3 files. The file 26.1.2 Compiling the code
The O'Caml SWIG module now requires you to compile a module ( % swig -ocaml -co swig.mli ; swig -ocaml co swig.ml % ocamlc -c swig.mli ; ocamlc -c swig.ml % ocamlc -c -ccopt "-I/usr/include/foo" example_wrap.c % ocamlc -c example.mli % ocamlc -c example.ml
% cp example_wrap.cxx example_wrap.cxx.c % ocamlc -c ... -ccopt -xc++ example_wrap.cxx.c % ... 26.1.3 The camlp4 module
The camlp4 module (swigp4.ml → swigp4.cmo) contains a simple rewriter which makes C++ code blend more seamlessly with objective caml code. It's use is optional, but encouraged. The source file is included in the Lib/ocaml directory of the SWIG source distribution. You can checkout this file with The basic principle of the module is to recognize certain non-caml expressions and convert them for use with C++ code as interfaced by SWIG. The camlp4 module is written to work with generated SWIG interfaces, and probably isn't great to use with anything else. Here are the main rewriting rules:
26.1.4 Using your moduleYou can test-drive your module by building a toplevel ocaml interpreter. Consult the ocaml manual for details. When linking any ocaml bytecode with your module, use the -custom option to build your functions into the primitive list. This option is not needed when you build native code. 26.1.5 Compilation problems and compiling with C++
As mentioned above, .cxx files need special handling to be compiled with 26.2 The low-level Ocaml/C interfaceIn order to provide access to overloaded functions, and provide sensible outputs from them, all C entities are represented as members of the c_obj type:
In the code as seen by the typemap writer, there is a value, swig_result, that always contains the current return data. It is a list, and must be appended with the caml_list_append function, or with functions and macros provided by objective caml. type c_obj = C_void | C_bool of bool | C_char of char | C_uchar of char | C_short of int | C_ushort of int | C_int of int | C_uint of int32 | C_int32 of int32 | C_int64 of int64 | C_float of float | C_double of float | C_ptr of int64 * int64 | C_array of c_obj array | C_list of c_obj list | C_obj of (string -> c_obj -> c_obj) | C_string of string | C_enum of c_enum_t A few functions exist which generate and return these:
Because of this style, a typemap can return any kind of value it wants from a function. This enables out typemaps and inout typemaps to work well. The one thing to remember about outputting values is that you must append them to the return list with swig_result = caml_list_append(swig_result,v). This function will return a new list that has your element appended. Upon return to caml space, the fnhelper function beautifies the result. A list containing a single item degrades to only that item (i.e. [ C_int 3 ] → C_int 3), and a list containing more than one item is wrapped in C_list (i.e. [ C_char 'a' ; C_char 'b' → C_list [ C_char 'a' ; C_char b ]). This is in order to make return values easier to handle when functions have only one return value, such as constructors, and operators. In addition, string, pointer, and object values are interchangeable with respect to caml_ptr_val, so you can allocate memory as caml strings and still use the resulting pointers for C purposes, even using them to construct simple objects on. Note, though, that foreign C++ code does not respect the garbage collector, although the SWIG interface does. The wild card type that you can use in lots of different ways is C_obj. It allows you to wrap any type of thing you like as an object using the same mechanism that the ocaml module does. When evaluated in caml_ptr_val, the returned value is the result of a call to the object's “&” operator, taken as a pointer. You should only construct values using objective caml, or using the functions caml_val_* functions provided as static functions to a SWIG ocaml module, as well as the caml_list_* functions. These functions provide everything a typemap needs to produce values. In addition, value items pass through directly, but you must make your own type signature for a function that uses value in this way. 26.2.1 The generated module
The SWIG You can introduce extra code into the output wherever you like with SWIG. These are the places you can introduce code:
26.2.2 EnumsSWIG will wrap enumerations as polymorphic variants in the output Ocaml code, as above in C_enum. In order to support all C++-style uses of enums, the function int_to_enum and enum_to_int are provided for ocaml code to produce and consume these values as integers. Other than that, correct uses of enums will not have a problem. Since enum labels may overlap between enums, the enum_to_int and int_to_enum functions take an enum type label as an argument. Example: %module enum_test %{ enum c_enum_type { a = 1, b, c = 4, d = 8 }; %} enum c_enum_type { a = 1, b, c = 4, d = 8 }; The output mli contains: type c_enum_type = [ `unknown | `c_enum_type ] type c_enum_tag = [ `int of int | `a | `b | `c | `d ] val int_to_enum c_enum_type -> int -> c_obj val enum_to_int c_enum_type -> c_obj -> c_obj So it's possible to do this: bash-2.05a$ ocamlmktop -custom enum_test_wrap.o enum_test.cmo -o enum_test_top bash-2.05a$ ./enum_test_top Objective Caml version 3.04 # open Enum_test ;; # let x = C_enum `a ;; val x : Enum_test.c_obj = C_enum `a # enum_to_int `c_enum_type x ;; - : Enum_test.c_obj = C_int 1 # int_to_enum `c_enum_type 4 ;; - : Enum_test.c_obj = C_enum `c 26.2.2.1 Enum typing in OcamlThe ocaml SWIG module now has support for loading and using multiple SWIG modules at the same time. This enhances modularity, but presents problems when used with a language which assumes that each module's types are complete at compile time. In order to achieve total soundness enum types are now isolated per-module. The type issue matters when values are shared between functions imported from different modules. You must convert values to master values using the swig_val function before sharing them with another module. 26.2.3 Arrays26.2.3.1 Simple types of bounded arraysSWIG has support for array types, but you generally will need to provide a typemap to handle them. You can currently roll your own, or expand some of the macros provided (but not included by default) with the SWIG distribution. By including “carray.i”, you will get access to some macros that help you create typemaps for array types fairly easily.
26.2.3.2 Complex and unbounded arraysUnfortunately, unbounded arrays and pointers can't be handled in a completely general way by SWIG, because the end-condition of such an array can't be predicted. In some cases, it will be by consent (e.g. an array of four or more chars), sometimes by explicit length (char *buffer, int len), and sometimes by sentinel value (0,-1,etc.). SWIG can't predict which of these methods will be used in the array, so you have to specify it for yourself in the form of a typemap. 26.2.3.3 Using an objectIt's possible to use C++ to your advantage by creating a simple object that provides access to your array. This may be more desirable in some cases, since the object can provide bounds checking, etc., that prevents crashes. Consider writing an object when the ending condition of your array is complex, such as using a required sentinel, etc. 26.2.3.4 Example typemap for a function taking float * and int
This is a simple example
26.2.4 C++ ClassesC++ classes, along with structs and unions are represented by C_obj (string → c_obj → c_obj) wrapped closures. These objects contain a method list, and a type, which allow them to be used like C++ objects. When passed into typemaps that use pointers, they degrade to pointers through their “&” method. Every method an object has is represented as a string in the object's method table, and each method table exists in memory only once. In addition to any other operators an object might have, certain builtin ones are provided by SWIG: (all of these take no arguments (C_void))
Note that this string belongs to the wrapper object, and not the underlying pointer, so using create_[x]_from_ptr alters the returned value for the same object. 26.2.4.1 STL vector and string ExampleStandard typemaps are now provided for STL vector and string. More are in the works. STL strings are passed just like normal strings, and returned as strings. STL string references don't mutate the original string, (which might be surprising), because Ocaml strings are mutable but have fixed length. Instead, use multiple returns, as in the argout_ref example.
Since there's a makefile in that directory, the example is easy to build. Here's a sample transcript of an interactive session using a string vector after making a toplevel (make toplevel). This example uses the camlp4 module. bash-2.05a$ ./example_top Objective Caml version 3.06 Camlp4 Parsing version 3.06 # open Swig ;; # open Example ;; # let x = new_StringVector '() ;; val x : Example.c_obj = C_obj <fun> # x -> ":methods" () ;; - : Example.c_obj = C_list [C_string "nop"; C_string "size"; C_string "empty"; C_string "clear"; C_string "push_back"; C_string "[]"; C_string "="; C_string "set"; C_string "~"; C_string "&"; C_string ":parents"; C_string ":classof"; C_string ":methods"] # x -> push_back ("foo") ;; - : Example.c_obj = C_void # x -> push_back ("bar") ;; - : Example.c_obj = C_void # x -> push_back ("baz") ;; - : Example.c_obj = C_void # x '[1] ;; - : Example.c_obj = C_string "bar" # x -> set (1,"spam") ;; - : Example.c_obj = C_void # x '[1] ;; - : Example.c_obj = C_string "spam" # for i = 0 to (x -> size() as int) - 1 do print_endline ((x '[i to int]) as string) done ;; foo bar baz - : unit = () # 26.2.4.2 C++ Class ExampleHere's a simple example using Trolltech's Qt Library:
26.2.4.3 Compiling the examplebash-2.05a$ QTPATH=/your/qt/path bash-2.05a$ for file in swig.mli swig.ml swigp4.ml ; do swig -ocaml -co $file ; done bash-2.05a$ ocamlc -c swig.mli ; ocamlc -c swig.ml bash-2.05a$ ocamlc -I `camlp4 -where` -pp "camlp4o pa_extend.cmo q_MLast.cmo" -c swigp4.ml bash-2.05a$ swig -ocaml -c++ -I$QTPATH/include qt.i bash-2.05a$ mv qt_wrap.cxx qt_wrap.c bash-2.05a$ ocamlc -c -ccopt -xc++ -ccopt -g -g -ccopt -I$QTPATH/include qt_wrap.c bash-2.05a$ ocamlc -c qt.mli bash-2.05a$ ocamlc -c qt.ml bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \ camlp4o.cma swigp4.cmo qt_wrap.o qt.cmo -o qt_top -cclib \ -L$QTPATH/lib -cclib -lqt 26.2.4.4 Sample Sessionbash-2.05a$ ./qt_top Objective Caml version 3.06 Camlp4 Parsing version 3.06 # open Swig ;; # open Qt ;; # let a = new_QApplication '(0,0) ;; val a : Qt.c_obj = C_obj <fun> # let hello = new_QPushButton '("hi",0) ;; val hello : Qt.c_obj = C_obj <fun> # hello -> resize (100,30) ;; - : Qt.c_obj = C_void # hello -> show () ;; - : Qt.c_obj = C_void # a -> exec () ;; Assuming you have a working installation of QT, you will see a window containing the string “hi” in a button. 26.2.5 Director Classes26.2.5.1 Director IntroductionDirector classes are classes which allow Ocaml code to override the public methods of a C++ object. This facility allows the user to use C++ libraries that require a derived class to provide application specific functionality in the context of an application or utility framework. You can turn on director classes by using an optional module argument like this: %module(directors="1") ... // Turn on the director class for a specific class like this: %feature("director") class foo { ... }; 26.2.5.2 Overriding Methods in Ocaml
Because the Ocaml language module treats C++ method calls as calls to a certain function, all you need to do is to define the function that will handle the method calls in terms of the public methods of the object, and any other relevant information. The function
In this example, I'll examine the objective caml code involved in providing an overloaded class. This example is contained in Examples/ocaml/shapes. 26.2.5.3 Director Usage Example
This is the meat of what you need to do. The actual “class” definition containing the overloaded method is defined in the function triangle_class. This is a lot like the class definitions emitted by SWIG, if you look at example.ml, which is generated when SWIG consumes example.i. Basically, you are given the arguments as a c_obj and the method name as a string, and you must intercept the method you are interested in and provide whatever return value you need. Bear in mind that the underlying C++ code needs the right return type, or an exception will be thrown. This exception will generally be Failure, or NotObject. You must call other ocaml methods that you rely on yourself. Due to the way directors are implemented, method calls on your object from with ocaml code will always invoke C++ methods even if they are overridden in ocaml.
In the example, the draw_shape_coverage function plots the indicated number of points as either covered ( 26.2.5.4 Creating director objectsThe definition of the actual object triangle can be described this way: let triangle = new_derived_object new_shape (triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0))) '()
The first argument to
The actual object passed to the self parameter of the director object will be a C_director_core, containing a c_obj option ref and a c_obj. The c_obj provided is the same object that will be returned from new_derived object, that is, the object exposing the overridden methods. The other part is an option ref that will have its value extracted before becoming the 26.2.5.5 Typemaps for directors, directorin, directorout, directorargout
Special typemaps exist for use with directors, the 26.2.5.6 directorin typemap
The 26.2.5.7 directorout typemap
The 26.2.5.8 directorargout typemap
C++ allows function arguments which are by pointer (*) and by reference (&) to receive a value from the called function, as well as sending one there. Sometimes, this is the main purpose of the argument given. 26.2.6 ExceptionsCatching exceptions is now supported using SWIG's %exception feature. A simple but not too useful example is provided by the throw_exception testcase in Examples/test-suite. You can provide your own exceptions, too. 27 SWIG and OctaveOctave is a high-level language intended for numerical programming that is mostly compatible with MATLAB. More information can be found at www.octave.org. This chapter is intended to give an introduction to using the module. You should also read the SWIG documentation that is not specific to Octave. Also, there are a dozen or so examples in the Examples/octave directory, and hundreds in the test suite (Examples/test-suite and Examples/test-suite/octave). 27.1 PreliminariesThe current SWIG implemention is based on Octave 2.9.12. Support for other versions (in particular the recent 3.0) has not been tested, nor has support for any OS other than Linux. 27.2 Running SWIGLet's start with a very simple SWIG interface file: %module example %{ #include "example.h" %} int gcd(int x, int y); extern double Foo;
To build an Octave module, run SWIG using the $ swig -octave -c++ example.i
This creates a C/C++ source file
The swig command line has a number of options you can use, like to redirect it's output. Use 27.2.1 Compiling a dynamic moduleOctave modules are DLLs/shared objects having the ”.oct” suffix. Building an oct file is usually done with the mkoctfile command (either within Octave itself, or from the shell). For example, $ swig -octave -c++ example.i -o example_wrap.cxx $ mkoctfile example_wrap.cxx example.c where example.c is the file containing the gcd() implementation. mkoctfile can also be used to extract the build parameters required to invoke the compiler and linker yourself. See the Octave manual and mkoctfile man page. mkoctfile will produce example.oct, which contains the compiled extension module. Loading it into Octave is then a matter of invoking octave:1> example 27.2.2 Using your module
Assuming all goes well, you will be able to do this: $ octave -q octave:1> example octave:2> example.gcd(4,6) ans = 2 octave:3> example.cvar.Foo ans = 3 octave:4> example.cvar.Foo=4; octave:5> example.cvar.Foo ans = 4 27.3 A tour of basic C/C++ wrapping27.3.1 ModulesThe SWIG module directive specifies the name of the Octave module. If you specify `module example', then in Octave everything in the module will be accessible under “example”, as in the above example. When choosing a module name, make sure you don't use the same name as a built-in Octave command or standard module name.
When Octave is asked to invoke
Giving this function a parameter “global” will cause it to load all symbols into the global namespace in addition to the $ octave -q octave:1> example("global") octave:2> gcd(4,6) ans = 2 octave:3> cvar.Foo ans = 3 octave:4> cvar.Foo=4; octave:5> cvar.Foo ans = 4
It is also possible to rename the module namespace with an assignment, as in: octave:1> example; octave:2> c=example; octave:3> c.gcd(10,4) ans = 2
All global variables are put into the cvar namespace object. This is accessible either as One can also rename it by simple assignment, e.g., octave:1> some_vars = cvar; 27.3.2 FunctionsGlobal functions are wrapped as new Octave built-in functions. For example, %module example int fact(int n);
creates a built-in function octave:1> example.fact(4) 24 27.3.3 Global variablesGlobal variables are a little special in Octave. Given a global variable: %module example extern double Foo; To expose variables, SWIG actually generates two functions, to get and set the value. In this case, Foo_set and Foo_set would be generated. SWIG then automatically calls these functions when you get and set the variable– in the former case creating a local copy in the interpreter of the C variables, and in the latter case copying an interpreter variables onto the C variable. octave:1> example; octave:2> c=example.cvar.Foo c = 3 octave:3> example.cvar.Foo=4; octave:4> c c = 3 octave:5> example.cvar.Foo ans = 4 If a variable is marked with the %immutable directive then any attempts to set this variable will cause an Octave error. Given a global variable: %module example %immutable; extern double Foo; %mutable;
SWIG will allow the the reading of octave:1> example octave:2> example.Foo=4 error: attempt to set immutable member variable error: assignment failed, or no method for `swig_type = scalar' error: evaluating assignment expression near line 2, column 12 It is possible to add new functions or variables to the module. This also allows the user to rename/remove existing functions and constants (but not linked variables, mutable or immutable). Therefore users are recommended to be careful when doing so. octave:1> example; octave:2> example.PI=3.142; octave:3> example.PI ans = 3.1420 27.3.4 Constants and enumsBecause Octave doesn't really have the concept of constants, C/C++ constants are not really constant in Octave. They are actually just a copy of the value into the Octave interpreter. Therefore they can be changed just as any other value. For example given some constants: %module example %constant int ICONST=42; #define SCONST "Hello World" enum Days{SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY}; This is 'effectively' converted into the following Octave code: example.ICONST=42 example.SCONST="Hello World" example.SUNDAY=0 .... 27.3.5 PointersC/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the <file.h> interface: C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the <file.h> interface: %module example FILE *fopen(const char *filename, const char *mode); int fputs(const char *, FILE *); int fclose(FILE *); When wrapped, you will be able to use the functions in a natural way from Octave. For example: octave:1> example; octave:2> f=example.fopen("w","junk"); octave:3> example.fputs("Hello world",f); octave:4> example.fclose(f); Simply printing the value of a wrapped C++ type will print it's typename. E.g., octave:1> example; octave:2> f=example.fopen("junk","w"); octave:3> f f = { _p_FILE, ptr = 0x9b0cd00 } As the user of the pointer, you are responsible for freeing it, or closing any resources associated with it (just as you would in a C program). This does not apply so strictly to classes and structs (see below). octave:1> example; octave:2> f=example.fopen("not there","r"); error: value on right hand side of assignment is undefined error: evaluating assignment expression near line 2, column 2 27.3.6 Structures and C++ classes
SWIG wraps C structures and C++ classes by using a special Octave type called a struct Point{ int x,y; }; is used as follows: octave:1> example; octave:2> p=example.Point(); octave:3> p.x=3; octave:4> p.y=5; octave:5> p.x, p.y ans = 3 ans = 5
In C++, invoking the type object in this way calls the object's constructor. The swig_ref type handles indexing operations such that usage maps closely to what you would have in C/C++. Structure members are accessed as in the above example, by calling set and get methods for C++ variables. Methods also work as expected. For example, code wrapped in the following way class Point{ public: int x,y; Point(int _x,int _y) : x(_x),y(_y) {} double distance(const Point& rhs) { return sqrt(pow(x-rhs.x,2)+pow(y-rhs.y,2)); } void set(int _x,int _y) { x=_x; y=_y; } }; can be used from Octave like this octave:1> example; octave:2> p1=example.Point(3,5); octave:3> p2=example.Point(1,2); octave:4> p1.distance(p2) ans = 3.6056
By using the octave:5> swig_this(p1) ans = 162504808 octave:6> swig_type(p1) ans = Point
Note that octave:7> a=struct('x',4) a = { x = 4 } octave:8> b=a b = { x = 4 } octave:9> b.y=4 b = { x = 4 y = 4 } octave:10> a a = { x = 4 } However, when dealing with wrapped objects, one gets the behavior octave:2> a=Point(3,5) a = { Point, ptr = 0x9afbbb0 } octave:3> b=a b = { Point, ptr = 0x9afbbb0 } octave:4> b.set(2,1); octave:5> b.x, b.y ans = 2 ans = 1 octave:6> a.x, a.y ans = 2 ans = 1
Depending on the ownership setting of a 27.3.7 C++ inheritance
Single and multiple inheritance are fully supported. The 27.3.8 C++ overloaded functions
Overloaded functions are supported, and handled as in other modules. That is, each overload is wrapped separately (under internal names), and a dispatch function is also emitted under the external/visible name. The dispatch function selects which overload to call (if any) based on the passed arguments. 27.3.9 C++ operators
C++ operator overloading is supported, in a way similar to other modules. The
For example, if By default the C++ operators are renamed to their corresponding Octave operators. So without doing any work, the following interface %inline { struct A { int value; A(int _value) : value(_value) {} A operator+ (const A& x) { return A(value+x.value); } }; } is usable from Octave like this: a=A(2), b=A(3), c=a+b assert(c.value==5); Octave operators are mapped in the following way: __brace a{args} __brace_asgn a{args} = rhs __paren a(args) __paren_asgn a(args) = rhs __str generates string rep __not !a __uplus +a __uminus -a __transpose a.' __hermitian a' __incr a++ __decr a-- __add a + b __sub a - b __mul a * b __div a / b __pow a ^ b __ldiv a \ b __lshift a <<b __rshift a >> b __lt a <b __le a <= b __eq a == b __ge a >= b __gt a > b __ne a != b __el_mul a .* b __el_div a ./ b __el_pow a .^ b __el_ldiv a .\ b __el_and a & b __el_or a | b On the C++ side, the default mappings are as follows: %rename(__add) *::operator+; %rename(__add) *::operator+(); %rename(__add) *::operator+() const; %rename(__sub) *::operator-; %rename(__uminus) *::operator-(); %rename(__uminus) *::operator-() const; %rename(__mul) *::operator*; %rename(__div) *::operator/; %rename(__mod) *::operator%; %rename(__lshift) *::operator< >; %rename(__el_and) *::operator&&; %rename(__el_or) *::operator||; %rename(__xor) *::operator^; %rename(__invert) *::operator~; %rename(__lt) *::operator ; %rename(__ge) *::operator>=; %rename(__eq) *::operator==; %rename(__ne) *::operator!=; %rename(__not) *::operator!; %rename(__incr) *::operator++; %rename(__decr) *::operator--; %rename(__paren) *::operator(); %rename(__brace) *::operator[]; 27.3.10 Class extension with %extendThe %extend directive works the same as in other modules.
You can use it to define special behavior, like for example defining Octave operators not mapped to C++ operators, or defining certain Octave mechanisms such as how an object prints. For example, the %extend A { string __str() { stringstream sout; sout<<$self->value; return sout.str(); } } Then in Octave one gets, octave:1> a=A(4); octave:2> a a = 4 octave:3> printf("%s\n",a); 4 octave:4> a.__str() 4 27.3.11 C++ templatesC++ class and function templates are fully supported as in other modules, in that the %template directive may used to create explicit instantiations of templated types. For example, function templates can be instantiated as follows: %module example %inline { template<class __scalar> __scalar mul(__scalar a,__scalar b) { return a*b; } } %include <std_complex.i> %template(mul) mul<std::complex<double> > %template(mul) mul<double> and then used from Octave octave:1> mul(4,3) ans = 12 octave:2> mul(4.2,3.6) ans = 15.120 octave:3> mul(3+4i,10+2i) ans = 22 + 46i Similarly, class templates can be instantiated as in the following example, %module example %include <std_complex.i> %include <std_string.i> %inline { #include <sstream> template<class __scalar> class sum { __scalar s; public: sum(__scalar _s=0) : s(_s) {} sum& add(__scalar _s) { s+=_s; return *this; } std::string __str() const { std::stringstream sout; sout<<s; return sout.str(); } }; } %template(sum_complex) sum<std::complex<double> >; %template(sum_double) sum<double>; and then used from Octave octave:2> a=sum_complex(2+3i); octave:3> a.add(2) ans = (4,3) octave:4> a.add(3+i) ans = (7,4) 27.3.12 C++ Smart PointersC++ smart pointers are fully supported as in other modules. 27.3.13 Directors (calling Octave from C++ code)There is full support for SWIG Directors, which permits Octave code to subclass C++ classes, and implement their virtual methods.
Octave has no direct support for object oriented programming, however the For example, octave:1> a=subclass(); octave:2> a.my_var = 4; octave:3> a.my_method = @(self) printf("my_var = ",self.my_var); octave:4> a.my_method(); my_var = 4
%inline { class A { public: virtual my_method() { printf("c-side routine called\n"); } }; void call_your_method(A& a) { a.my_method(); } } Then from Octave you can say: octave:1> B=@() subclass(A(),@my_method); octave:2> function my_method(self) octave:3> printf("octave-side routine called\n"); octave:4> end octave:5> call_your_method(B()); octave-side routine called or more concisely, octave:1> B=@() subclass(A(),'my_method',@(self) printf("octave-side routine called\n")); octave:2> call_your_method(B()); octave-side routine called Note that you have to enable directors via the %feature directive (see other modules for this).
octave:1> B=@(some_var=2) subclass(A(),'some_var',some_var,@some_func,'another_func',@(self) do_stuff()) You can also assign non-C++ member variables and functions after construct time. There is no support for non-C++ static members. There is limited support for explicitly referencing C++ bases. So, in the example above, we could have octave:1> B=@() subclass(A(),@my_method); octave:2> function my_method(self) octave:3> self.A.my_method(); octave:4> printf("octave-side routine called\n"); octave:5> end octave:6> call_your_method(B()); c-side routine called octave-side routine called 27.3.14 ThreadsThe use of threads in wrapped Director code is not supported; i.e., an Octave-side implementation of a C++ class must be called from the Octave interpreter's thread. Anything fancier (apartment/queue model, whatever) is left to the user. Without anything fancier, this amounts to the limitation that Octave must drive the module… like, for example, an optimization package that calls Octave to evaluate an objective function. 27.3.15 Memory management
As noted above, For example, %inline { class A { public: A() { printf("A constructing\n"); } ~A() { printf("A destructing\n"); } }; } Would produce this behavior in Octave: octave:1> a=A(); A constructing octave:2> b=a; octave:3> clear a; octave:4> b=4; A destructing The %newobject directive may be used to control this behavior for pointers returned from functions.
In the case where one wishes for the C++ side to own an object that was created in Octave (especially a Director object), one can use the __disown() method to invert this logic. Then letting the Octave reference count go to zero will not destroy the object, but destroying the object will invalidate the Octave-side object if it still exists (and call destructors of other C++ bases in the case of multiple inheritance/ 27.3.16 STL supportThis is some skeleton support for various STL containers. 27.3.17 Matrix typemapsOctave provides a rich set of classes for dealing with matrices. Currently there are no built-in typemaps to deal with those. However, these are relatively straight forward for users to add themselves (see the docs on typemaps). Without much work (a single typemap decl– say, 5 lines of code in the interface file), it would be possible to have a function double my_det(const double* mat,int m,int n); that is accessed from Octave as, octave:1> my_det(rand(4)); ans = -0.18388
28 SWIG and Perl5Caution: This chapter is under repair! This chapter describes SWIG's support of Perl5. Although the Perl5 module is one of the earliest SWIG modules, it has continued to evolve and has been improved greatly with the help of SWIG users. For the best results, it is recommended that SWIG be used with Perl5.003 or later. Earlier versions are problematic and SWIG generated extensions may not compile or run correctly. 28.1 OverviewTo build Perl extension modules, SWIG uses a layered approach. At the lowest level, simple procedural wrappers are generated for functions, classes, methods, and other declarations in the input file. Then, for structures and classes, an optional collection of Perl proxy classes can be generated in order to provide a more natural object oriented Perl interface. These proxy classes simply build upon the low-level interface. In describing the Perl interface, this chapter begins by covering the essentials. First, the problem of configuration, compiling, and installing Perl modules is discussed. Next, the low-level procedural interface is presented. Finally, proxy classes are described. Advanced customization features, typemaps, and other options are found near the end of the chapter. 28.2 Preliminaries
To build a Perl5 module, run Swig using the swig -perl example.i
This produces two files. The first file,
To build the module, you will need to compile the file 28.2.1 Getting the right header filesIn order to compile, SWIG extensions need the following Perl5 header files : #include "Extern.h" #include "perl.h" #include "XSUB.h" These are typically located in a directory like this /usr/lib/perl5/5.00503/i386-linux/CORE The SWIG configuration script automatically tries to locate this directory so that it can compile examples. However, if you need to find out where the directory is loaded, an easy way to find out is to run Perl itself. % perl -e 'use Config; print $Config{archlib};' /usr/lib/perl5/5.00503/i386-linux 28.2.2 Compiling a dynamic moduleThe preferred approach to building an extension module is to compile it into a shared object file or DLL. To do this, you will need to compile your program using commands like this (shown for Linux): $ swig -perl example.i % gcc example.c % gcc -c example_wrap.c -I/usr/lib/perl5/5.00503/i386-linux/CORE -Dbool=char % gcc -shared example.o example_wrap.o -o example.so
The exact compiler options 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
When linking the module, the name of the shared object file must match the module name used in the SWIG interface file. If you used ` 28.2.3 Building a dynamic module with MakeMakerIt is also possible to use Perl to build dynamically loadable modules for you using the MakeMaker utility. To do this, write a Perl script such as the following : # File : Makefile.PL use ExtUtils::MakeMaker; WriteMakefile( `NAME' => `example', # Name of package `LIBS' => [`-lm'], # Name of custom libraries `OBJECT' => `example.o example_wrap.o' # Object files ); Now, to build a module, simply follow these steps : % perl Makefile.PL % make % make install If you are planning to distribute a SWIG-generated module, this is the preferred approach to compilation. More information about MakeMaker can be found in “Programming Perl, 2nd ed.” by Larry Wall, Tom Christiansen, and Randal Schwartz. 28.2.4 Building a static version of PerlIf you machine does not support dynamic loading or if you've tried to use it without success, you can build a new version of the Perl interpreter with your SWIG extensions added to it. To build a static extension, you first need to invoke SWIG as follows : % swig -perl -static example.i
By default SWIG includes code for dynamic loading, but the
Next, you will need to supply a %module example %inline %{ extern double My_variable; extern int fact(int); %} // Include code for rebuilding Perl %include <perlmain.i> The same thing can be accomplished by running SWIG as follows : % swig -perl -static -lperlmain.i example.i
The To build your new Perl executable, follow the exact same procedure as for a dynamic module, but change the link line to something like this: % gcc example.o example_wrap.o -L/usr/lib/perl5/5.00503/i386-linux/CORE \ -lperl -lsocket -lnsl -lm -o myperl
This will produce a new version of Perl called 28.2.5 Using the module
To use the module, simply use the Perl $ perl use example; print example::fact(4),"\n"; 24 A common error received by first-time users is the following: use example; Can't locate example.pm in @INC (@INC contains: /usr/lib/perl5/5.00503/i386-lin ux /usr/lib/perl5/5.00503 /usr/lib/perl5/site_perl/5.005/i386-linux /usr/lib/pe rl5/site_perl/5.005 .) at - line 1. BEGIN failed--compilation aborted at - line 1.
This error is almost caused when the name of the shared object file you created doesn't match the module name you specified with the A somewhat related, but slightly different error is this: use example; Can't find 'boot_example' symbol in ./example.so at - line 1 BEGIN failed--compilation aborted at - line 1. This error is generated because Perl can't locate the module bootstrap function in the SWIG extension module. This could be caused by a mismatch between the module name and the shared library name. However, another possible cause is forgetting to link the SWIG-generated wrapper code with the rest of your application when you linked the extension module. Another common error is the following: use example; Can't load './example.so' for module example: ./example.so: undefined symbol: Foo at /usr/lib/perl5/5.00503/i386-linux/DynaLoader.pm line 169. at - line 1 BEGIN failed--compilation aborted at - line 1. 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.
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 Finally, suppose that your extension module is linked with another library like this: $ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \ -o example.so
If the use example; Can't load './example.so' for module example: libfoo.so: cannot open shared object file: No such file or directory at /usr/lib/perl5/5.00503/i386-linux/DynaLoader.pm line 169. at - line 1 BEGIN failed--compilation aborted at - line 1. >>>
This error is generated because the dynamic linker can't locate the $ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \ -Xlinker -rpath /home/beazley/projects/lib \ -o example.so
Alternatively, you can set the $ env LD_LIBRARY_PATH=/home/beazley/projects/lib perl
Finally, you can use a command such as 28.2.6 Compilation problems and compiling with C++Compilation of C++ extensions has traditionally been a tricky problem. Since the Perl interpreter is written in C, you need to take steps to make sure C++ is properly initialized and that modules are compiled correctly. On most machines, C++ extension modules should be linked using the C++ compiler. For example: % swig -c++ -perl example.i % g++ -c example.cxx % g++ -c example_wrap.cxx -I/usr/lib/perl5/5.00503/i386-linux/CORE % g++ -shared example.o example_wrap.o -o example.so
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 % swig -c++ -perl example.i % g++ -c example.cxx % g++ -c example_wrap.cxx -I/usr/lib/perl5/5.00503/i386-linux/CORE % g++ -shared example.o example_wrap.o -o example.so -lCrun Of course, the names of the extra libraries are completely non-portable—you will probably need to do some experimentation. Another possible compile problem comes from recent versions of Perl (5.8.0) and the GNU tools. If you see errors having to do with _crypt_struct, that means _GNU_SOURCE is not defined and it needs to be. So you should compile the wrapper like: % g++ -c example_wrap.cxx -I/usr/lib/perl/5.8.0/CORE -D_GNU_SOURCE -D_GNU_SOURCE is also included in the Perl ccflags, which can be found by running % perl -e 'use Config; print $Config{ccflags};' So you could also compile the wrapper like % g++ -c example_wrap.cxx -I/usr/lib/perl/5.8.0/CORE \ `perl -e 'use Config; print $Config{ccflags}'` Sometimes people have suggested that it is necessary to relink the Perl 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 on most platforms. 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 Perl.
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 $ 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) $ If linking wasn't enough of a problem, another major complication 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 Perl, 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. Also, be aware that certain C++ features, especially RTTI, can behave strangely when working with multiple modules.
It should be noted that you may get a lot of error messages about the `
Finally, recent versions of Perl (5.8.0) have namespace conflict problems. Perl defines a bunch of short macros to make the Perl API function names shorter. For example, in /usr/lib/perl/5.8.0/CORE/embed.h there is a line: #define do_open Perl_do_open The problem is, in the <iostream> header from GNU libstdc++v3 there is a private function named do_open. If <iostream> is included after the perl headers, then the Perl macro causes the iostream do_open to be renamed, which causes compile errors. Hopefully in the future Perl will support a PERL_NO_SHORT_NAMES flag, but for now the only solution is to undef the macros that conflict. Lib/perl5/noembed.h in the SWIG source has a list of macros that are known to conflict with either standard headers or other headers. But if you get macro type conflicts from other macros not included in Lib/perl5/noembed.h while compiling the wrapper, you will have to find the macro that conflicts and add an #undef into the .i file. Please report any conflicting macros you find to swig-user mailing list. 28.2.7 Compiling for 64-bit platformsOn 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. To utilize 64-bits, the Perl 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. 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). 28.3 Building Perl Extensions under WindowsBuilding a SWIG extension to Perl under Windows is roughly similar to the process used with Unix. Normally, you will want to produce a DLL that can be loaded into the Perl interpreter. This section assumes you are using SWIG with Microsoft Visual C++ although the procedure may be similar with other compilers. 28.3.1 Running SWIG from Developer StudioIf you are developing your application within Microsoft developer studio, SWIG can be invoked as a custom build option. The process roughly requires these steps :
Now, assuming you made it this far, 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 Perl extension, simply run Perl and use the use command as normal. For example : DOS > perl use example; $a = example::fact(4); print "$a\n"; 28.3.2 Using other compilersSWIG is known to work with Cygwin and may work with other compilers on Windows. For general hints and suggestions refer to the Windows chapter. 28.4 The low-level interfaceAt its core, the Perl module uses a simple low-level interface to C function, variables, constants, and classes. This low-level interface can be used to control your application. However, it is also used to construct more user-friendly proxy classes as described in the next section. 28.4.1 FunctionsC functions are converted into new Perl built-in commands (or subroutines). For example: %module example int fact(int a); ... Now, in Perl: use example; $a = &example::fact(2); 28.4.2 Global variablesGlobal variables are handled using Perl's magic variable mechanism. SWIG generates a pair of functions that intercept read/write operations and attaches them to a Perl variable with the same name as the C global variable. Thus, an interface like this %module example; ... double Spam; ... is accessed as follows : use example; print $example::Spam,"\n"; $example::Spam = $example::Spam + 4 # ... etc ...
If a variable is declared as
To make ordinary variables read-only, you can also use the %{ extern char *path; %} %immutable; extern char *path; %mutable;
The It is also possible to tag a specific variable as read-only like this: %{ extern char *path; %} %immutable path; ... ... extern char *path; // Declared later in the input 28.4.3 ConstantsBy default, constants are wrapped as read-only Perl variables. For example: %module example #define FOO 42 In Perl: use example; print $example::FOO,"\n"; # OK $example::FOO = 2; # Error
Alternatively, if you use swig's use example; print example::FOO,"\n"; 28.4.4 PointersSWIG represents pointers as blessed references. A blessed reference is the same as a Perl reference except that it has additional information attached to it indicating what kind of reference it is. That is, if you have a C declaration like this : Matrix *new_Matrix(int n, int m); The module returns a value generated as follows: $ptr = new_Matrix(int n, int m); # Save pointer return result bless $ptr, "p_Matrix"; # Bless it as a pointer to Matrix SWIG uses the “blessing” to check the datatype of various pointers. In the event of a mismatch, an error or warning message is generated.
To check to see if a value is the NULL pointer, use the if (defined($ptr)) { print "Not a NULL pointer."; } else { print "Is a NULL pointer."; }
To create a NULL pointer, you should pass the
The “value” of a Perl reference is not the same as the underlying C pointer that SWIG wrapper functions return. Suppose that if ($$a == $$b) { print "a and b point to the same thing in C"; } else { print "a and b point to different objects."; } As much as you might be inclined to modify a pointer value directly from Perl, don't. Manipulating pointer values is architecture dependent and could cause your program to crash. Similarly, don't try to manually cast a pointer to a new type by reblessing a pointer. 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: %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; } %}
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
Compatibility Note: In earlier versions, SWIG tried to preserve the same pointer naming conventions as XS and 28.4.5 StructuresAccess to the contents of a structure are provided through a set of low-level accessor functions as described in the “SWIG Basics” chapter. For example, struct Vector { double x,y,z; }; gets mapped into the following collection of accessor functions: struct Vector *new_Vector(); void delete_Vector(Vector *v); double Vector_x_get(Vector *obj) void Vector_x_set(Vector *obj, double x) double Vector_y_get(Vector *obj) void Vector_y_set(Vector *obj, double y) double Vector_z_get(Vector *obj) void Vector_z_set(Vector *obj, double z) These functions are then used to access structure data from Perl as follows: $v = example::new_Vector(); print example::Vector_x_get($v),"\n"; # Get x component example::Vector_x_set($v,7.8); # Change x component Similar access is provided for unions and the data members of C++ classes.
struct Foo { ... %immutable; int x; /* Read-only members */ char *name; %mutable; ... };
When Array members are normally wrapped as read-only. For example, struct Foo { int x[50]; }; produces a single accessor function like this: int *Foo_x_get(Foo *self) { return self->x; };
If you want to set an array member, you will need to supply a “memberin” typemap described later in this chapter. As a special case, SWIG does generate code to set array members of type When structure members are wrapped, they are handled as pointers. For example, struct Foo { ... }; struct Bar { Foo f; }; generates accessor functions such as this: Foo *Bar_f_get(Bar *b) { return &b->f; } void Bar_f_set(Bar *b, Foo *val) { b->f = *val; } 28.4.6 C++ classesC++ classes are wrapped by building a set of low level accessor functions. Consider the following class : class List { public: List(); ~List(); int search(char *item); void insert(char *item); void remove(char *item); char *get(int n); int length; static void print(List *l); }; When wrapped by SWIG, the following functions are created : List *new_List(); void delete_List(List *l); int List_search(List *l, char *item); void List_insert(List *l, char *item); void List_remove(List *l, char *item); char *List_get(List *l, int n); int List_length_get(List *l); void List_length_set(List *l, int n); void List_print(List *l); In Perl, these functions are used in a straightforward manner: use example; $l = example::new_List(); example::List_insert($l,"Ale"); example::List_insert($l,"Stout"); example::List_insert($l,"Lager") example::List_print($l) Lager Stout Ale print example::List_length_get($l),"\n"; 3 At this low level, C++ objects are really just typed pointers. Member functions are accessed by calling a C-like wrapper with an instance pointer as the first argument. Although this interface is fairly primitive, it provides direct access to C++ objects. A higher level interface using Perl proxy classes can be built using these low-level accessors. This is described shortly. 28.4.7 C++ classes and type-checkingThe SWIG type-checker is fully aware of C++ inheritance. Therefore, if you have classes like this class Foo { ... }; class Bar : public Foo { ... }; and a function void spam(Foo *f);
then the function 28.4.8 C++ overloaded functions
If you have a C++ program with overloaded functions or methods, you will need to disambiguate those methods using /* Forward renaming declarations */ %rename(foo_i) foo(int); %rename(foo_d) foo(double); ... void foo(int); // Becomes 'foo_i' void foo(char *c); // Stays 'foo' (not renamed) class Spam { public: void foo(int); // Becomes 'foo_i' void foo(double); // Becomes 'foo_d' ... }; Now, in Perl, the methods are accessed as follows: use example; example::foo_i(3); $s = example::new_Spam(); example::Spam_foo_i($s,3); example::Spam_foo_d($s,3.14); Please refer to the “SWIG Basics” chapter for more information. 28.4.9 OperatorsAs of version 1.3.27 SWIG automatically renames the most common C++ operators, and maps them into the perl module with the proper 'use overload …' so you don't need to do any work. The following C++ operators are currently supported by the Perl module:
28.4.10 Modules and packages
When you create a SWIG extension, everything gets placed into a single Perl module. The name of the module is determined by the % perl5 use example; # load the example module print example::fact(4),"\n" # Call a function in it 24 Usually, a module consists of a collection of code that is contained within a single file. A package, on the other hand, is the Perl equivalent of a namespace. A package is a lot like a module, except that it is independent of files. Any number of files may be part of the same package–or a package may be broken up into a collection of modules if you prefer to think about it in this way. SWIG installs its functions into a package with the same name as the module. Incompatible Change: previous versions of SWIG enabled you to change the name of the package by using the -package option, this feature has been removed in order to properly support modules that used nested namespaces, e.g. Foo::Bar::Baz. To give your module a nested namespace simply provide the fully qualified name in your %module directive: %module "Foo::Bar::Baz" NOTE: the double quotes are necessary.
Using the %module(package="XML::Xerces") "XML::Xerces::SAX
And now all the applications could use the class 28.5 Input and output parametersA common problem in some C programs is handling parameters passed as simple pointers. For example: void add(int x, int y, int *result) { *result = x + y; } or perhaps int sub(int *x, int *y) { return *x+*y; }
The easiest way to handle these situations is to use the %module example %include "typemaps.i" void add(int, int, int *OUTPUT); int sub(int *INPUT, int *INPUT); In Perl, this allows you to pass simple values. For example: $a = example::add(3,4); print "$a\n"; 7 $b = example::sub(7,4); print "$b\n"; 3
Notice how the
If you don't want to use the names %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); If a function mutates one of its parameters like this, void negate(int *x) { *x = -(*x); }
you can use %include "typemaps.i" ... void negate(int *INOUT); In Perl, a mutated parameter shows up as a return value. For example: $a = example::negate(3); print "$a\n"; -3 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: /* send message, return number of bytes sent, along with success code */ int send_message(char *text, int len, int *success);
To wrap such a function, simply use the %module example %include "typemaps.i" %apply int *OUTPUT { int *success }; ... int send_message(char *text, int *success); When used in Perl, the function will return multiple values. ($bytes, $success) = example::send_message("Hello World"); Another common use of multiple return values are in query functions. For example: void get_dimensions(Matrix *m, int *rows, int *columns); To wrap this, you might use the following: %module example %include "typemaps.i" %apply int *OUTPUT { int *rows, int *columns }; ... void get_dimensions(Matrix *m, int *rows, *columns); Now, in Perl: ($r,$c) = example::get_dimensions($m);
In certain cases, it is possible to treat Perl references as C pointers. To do this, use the %module example %include "typemaps.i" void add(int x, int y, int *REFERENCE); In Perl: use example; $c = 0.0; example::add(3,4,\$c); print "$c\n"; 7
Note: The 28.6 Exception handling
The SWIG 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(); } } }; Since several methods in this class can throw an exception for an out-of-bounds access, you might want to catch this in the Perl extension by writing the following in an interface file: %exception { try { $action } catch (RangeError) { croak("Array index out-of-bounds"); } } class DoubleArray { ... };
The exception handling code is inserted directly into generated wrapper functions. The 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: %exception getitem { try { $action } catch (RangeError) { croak("Array index out-of-bounds"); } } %exception setitem { try { $action } catch (RangeError) { croak("Array index out-of-bounds"); } }
In this case, the exception handler is only attached to methods and functions named If you had a lot of different methods, you can avoid extra typing by using a macro. For example: %define RANGE_ERROR { try { $action } catch (RangeError) { croak("Array index out-of-bounds"); } } %enddef %exception getitem RANGE_ERROR; %exception setitem RANGE_ERROR; Since SWIG's exception handling is user-definable, you are not limited to C++ exception handling. See the chapter on “Customization features” for more examples.
Compatibility note: In SWIG1.1, exceptions were defined using the older %except(python) { try { $function } catch (RangeError) { croak("Array index out-of-bounds"); } }
This is still supported, but it is deprecated. The newer 28.7 Remapping datatypes with typemaps
This section describes how you can modify SWIG's default wrapping behavior for various C/C++ datatypes using the 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-Perl interface. 28.7.1 A simple typemap exampleA typemap is nothing more than a code generation rule that is attached to a specific C datatype. For example, to convert integers from Perl to C, you might define a typemap like this: %module example %typemap(in) int { $1 = (int) SvIV($input); printf("Received an integer : %d\n", $1); } ... %inline %{ extern int fact(int n); %}
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 When this example is used in Perl5, it will operate as follows : use example; $n = example::fact(6); print "$n\n"; ... Output : Received an integer : 6 720
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 %typemap(in) int n { $1 = (int) SvIV($input); printf("n = %d\n",$1); } %inline %{ typedef int Integer; extern int fact(Integer n); // Above typemap is applied %}
It should be noted that the matching of Typemaps can also be defined for groups of consecutive arguments. For example: %typemap(in) (char *str, unsigned len) { $1 = SvPV($input,$2); }; int count(char c, char *str, unsigned len); When a multi-argument typemap is defined, the arguments are always handled as a single Perl object. This allows the function to be used like this (notice how the length parameter is omitted): example::count("e","Hello World"); 1 >>> 28.7.2 Perl5 typemapsThe previous section illustrated an “in” typemap for converting Perl objects to C. A variety of different typemap methods are defined by the Perl module. For example, to convert a C integer back into a Perl object, you might define an “out” typemap like this: %typemap(out) int { $result = sv_newmortal(); set_setiv($result, (IV) $1); argvi++; } The following typemap methods are available:
Converts Perl5 object to input function arguments.
Converts function return value to a Perl5 value.
Converts a Perl5 object to a global variable.
Converts a global variable to a Perl5 object.
Cleans up a function argument after a function call
Output argument handling
Clean up return value from a function.
Setting of C++ member data (all languages).
Return of C++ member data (all languages).
Check value of input parameter. 28.7.3 Typemap variables
Within typemap code, a number of special variables prefaced with a
A C local variable corresponding to the actual type specified in the
A Perl object holding the value of an argument of variable value.
A Perl object that holds the result to be returned to Perl.
The parameter name that was matched.
The actual C datatype matched by the typemap.
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
The Perl name of the wrapper function being created. 28.7.4 Useful functionsWhen writing typemaps, it is necessary to work directly with Perl5 objects. This, unfortunately, can be a daunting task. Consult the “perlguts” man-page for all of the really ugly details. A short summary of commonly used functions is provided here for reference. It should be stressed that SWIG can be used quite effectively without knowing any of these details–especially now that there are typemap libraries that can already been written. Perl Integer Functions int SvIV(SV *); void sv_setiv(SV *sv, IV value); SV *newSViv(IV value); int SvIOK(SV *); Perl Floating Point Functions double SvNV(SV *); void sv_setnv(SV *, double value); SV *newSVnv(double value); int SvNOK(SV *); Perl String Functions char *SvPV(SV *, STRLEN len); void sv_setpv(SV *, char *val); void sv_setpvn(SV *, char *val, STRLEN len); SV *newSVpv(char *value, STRLEN len); int SvPOK(SV *); void sv_catpv(SV *, char *); void sv_catpvn(SV *, char *, STRLEN); Perl References void sv_setref_pv(SV *, char *, void *ptr); int sv_isobject(SV *); SV *SvRV(SV *); int sv_isa(SV *, char *0; 28.8 Typemap Examples
This section includes a few examples of typemaps. For more examples, you might look at the files “ 28.8.1 Converting a Perl5 array to a char %%**%%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 Perl5 array reference to be used as a char ** datatype. %module argv // This tells SWIG to treat char ** as a special case %typemap(in) char ** { AV *tempav; I32 len; int i; SV **tv; if (!SvROK($input)) croak("Argument $argnum is not a reference."); if (SvTYPE(SvRV($input)) != SVt_PVAV) croak("Argument $argnum is not an array."); tempav = (AV*)SvRV($input); len = av_len(tempav); $1 = (char **) malloc((len+2)*sizeof(char *)); for (i = 0; i <= len; i++) { tv = av_fetch(tempav, i, 0); $1[i] = (char *) SvPV(*tv,PL_na); } $1[i] = NULL; }; // This cleans up the char ** array after the function call %typemap(freearg) char ** { free($1); } // Creates a new Perl array and places a NULL-terminated char ** into it %typemap(out) char ** { AV *myav; SV **svs; int i = 0,len = 0; /* Figure out how many elements we have */ while ($1[len]) len++; svs = (SV **) malloc(len*sizeof(SV *)); for (i = 0; i < len ; i++) { svs[i] = sv_newmortal(); sv_setpv((SV*)svs[i],$1[i]); }; myav = av_make(len,svs); free(svs); $result = newRV_noinc((SV*)myav); sv_2mortal($result); argvi++; } // Now a few 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; } // Returns a char ** list char **get_args() { static char *values[] = { "Dave", "Mike", "Susan", "John", "Michelle", 0}; return &values[0]; } %} When this module is compiled, the wrapped C functions can be used in a Perl script as follows : use argv; @a = ("Dave", "Mike", "John", "Mary"); # Create an array of strings argv::print_args(\@a); # Pass it to our C function $b = argv::get_args(); # Get array of strings from C print @$b,"\n"; # Print it out 28.8.2 Return values
Return values are placed on the argument stack of each wrapper function. The current value of the argument stack pointer is contained in a variable
The total number of return values should not exceed the number of input values unless you explicitly extend the argument stack. This can be done using the %typemap(argout) int *OUTPUT { if (argvi >= items) { EXTEND(sp,1); /* Extend the stack by 1 object */ } $result = sv_newmortal(); sv_setiv($target,(IV) *($1)); argvi++; } 28.8.3 Returning values from arguments
Sometimes it is desirable for a function to return a value in one of its arguments. This example describes the implementation of the %module return // This tells SWIG to treat an double * argument with name 'OutDouble' as // an output value. %typemap(argout) double *OUTPUT { $result = sv_newmortal(); sv_setnv($result, *$input); argvi++; /* Increment return count -- important! */ } // We don't care what the input value is. Ignore, but set to a temporary variable %typemap(in,numinputs=0) double *OUTPUT(double junk) { $1 = &junk; } // Now a function to test it %{ /* Returns the first two input arguments */ int multout(double a, double b, double *out1, double *out2) { *out1 = a; *out2 = b; return 0; }; %} // If we name both parameters OutDouble both will be output int multout(double a, double b, double *OUTPUT, double *OUTPUT); ... When this function is called, the output arguments are appended to the stack used to return results. This shows up an array in Perl. For example : @r = multout(7,13); print "multout(7,13) = @r\n"; ($x,$y) = multout(7,13); 28.8.4 Accessing array structure membersConsider the following data structure : #define SIZE 8 typedef struct { int values[SIZE]; ... } Foo; By default, SWIG doesn't know how to the handle the values structure member it's an array, not a pointer. In this case, SWIG makes the array member read-only. Reading will simply return a pointer to the first item in the array. To make the member writable, a “memberin” typemap can be used. %typemap(memberin) int [SIZE] { int i; for (i = 0; i < SIZE; i++) { $1[i] = $input[i]; } }
Whenever a As in the previous example, the typemap can be generalized for any dimension. For example: %typemap(memberin) int [ANY] { int i; for (i = 0; i < $1_dim0; i++) { $1[i] = $input[i]; } }
When setting structure members, the input object is always assumed to be a C array of values that have already been converted from the target language. Because of this, the 28.8.5 Turning Perl references into C pointersA frequent confusion on the SWIG mailing list is errors caused by the mixing of Perl references and C pointers. For example, suppose you have a C function that modifies its arguments like this : void add(double a, double b, double *c) { *c = a + b; } A common misinterpretation of this function is the following Perl script : # Perl script $a = 3.5; $b = 7.5; $c = 0.0; # Output value add($a,$b,\$c); # Place result in c (Except that it doesn't work) To make this work with a reference, you can use a typemap such as this: %typemap(in) double * (double dvalue) { SV* tempsv; if (!SvROK($input)) { croak("expected a reference\n"); } tempsv = SvRV($input); if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) { croak("expected a double reference\n"); } dvalue = SvNV(tempsv); $1 = &dvalue; } %typemap(argout) double * { SV *tempsv; tempsv = SvRV($input); sv_setnv(tempsv, *$1); } Now, if you place this before the add function, you can do this : $a = 3.5; $b = 7.5; $c = 0.0; add($a,$b,\$c); # Now it works! print "$c\n"; 28.8.6 Pointer handlingOccasionally, it might be necessary to convert pointer values that have been stored using the SWIG typed-pointer representation. To convert a pointer from Perl to C, the following function is used:
Converts a Perl object
Creates a new Perl pointer object.
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 Foo *f; if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0) == -1) return NULL; SV *sv = sv_newmortal(); SWIG_MakePtr(sv, f, SWIGTYPE_p_Foo, 0);
In a typemap, the type descriptor should always be accessed using the special typemap variable %typemap(in) Foo * { if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,0)) == -1) return NULL; }
If necessary, the descriptor for any type can be obtained using the %typemap(in) Foo * { if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 0)) == -1) return NULL; } 28.9 Proxy classesOut of date. Needs update. Using the low-level procedural interface, SWIG can also construct a high-level object oriented interface to C structures and C++ classes. This is done by constructing a Perl proxy class (also known as a shadow class) that provides an OO wrapper to the underlying code. This section describes the implementation details of the proxy interface. 28.9.1 Preliminaries
Proxy classes, are generated by default. If you want to turn them off, use the $ swig -c++ -perl -noproxy example.i
When proxy classes are used, SWIG moves all of the low-level procedural wrappers to another package name. By default, this package is named 'modulec' where 'module' is the name of the module you provided with the 28.9.2 Structure and class wrappersSuppose you have the following SWIG interface file : %module example struct Vector { Vector(double x, double y, double z); ~Vector(); double x,y,z; }; When wrapped, SWIG creates the following set of low-level accessor functions as described in previous sections. Vector *new_Vector(double x, double y, double z); void delete_Vector(Vector *v); double Vector_x_get(Vector *v); double Vector_x_set(Vector *v, double value); double Vector_y_get(Vector *v); double Vector_y_set(Vector *v, double value); double Vector_z_get(Vector *v); double Vector_z_set(Vector *v, double value); However, when proxy classes are enabled, these accessor functions are wrapped inside a Perl class like this: package example::Vector; @ISA = qw( example ); %OWNER = (); %BLESSEDMEMBERS = (); sub new () { my $self = shift; my @args = @_; $self = vectorc::new_Vector(@args); return undef if (!defined($self)); bless $self, "example::Vector"; $OWNER{$self} = 1; my %retval; tie %retval, "example::Vector", $self; return bless \%retval,"Vector"; } sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); delete $ITERATORS{$self}; if (exists $OWNER{$self}) { examplec::delete_Vector($self)); delete $OWNER{$self}; } sub FETCH { my ($self,$field) = @_; my $member_func = "vectorc::Vector_${field}_get"; my $val = &$member_func($self); if (exists $BLESSEDMEMBERS{$field}) { return undef if (!defined($val)); my %retval; tie %retval,$BLESSEDMEMBERS{$field},$val; return bless \%retval, $BLESSEDMEMBERS{$field}; } return $val; } sub STORE { my ($self,$field,$newval) = @_; my $member_func = "vectorc::Vector_${field}_set"; if (exists $BLESSEDMEMBERS{$field}) { &$member_func($self,tied(%{$newval})); } else { &$member_func($self,$newval); } }
Each structure or class is mapped into a Perl package of the same name. The C++ constructors and destructors are mapped into constructors and destructors for the package and are always named “new” and “DESTROY”. The constructor always returns a tied hash table. This hash table is used to access the member variables of a structure in addition to being able to invoke member functions. The To use our new proxy class we can simply do the following: # Perl code using Vector class $v = new Vector(2,3,4); $w = Vector->new(-1,-2,-3); # Assignment of a single member $v->{x} = 7.5; # Assignment of all members %$v = ( x=>3, y=>9, z=>-2); # Reading members $x = $v->{x}; # Destruction $v->DESTROY(); 28.9.3 Object OwnershipIn order for proxy classes to work properly, it is necessary for Perl to manage some mechanism of object ownership. Here's the crux of the problem—suppose you had a function like this : Vector *Vector_get(Vector *v, int index) { return &v[i]; } This function takes a Vector pointer and returns a pointer to another Vector. Such a function might be used to manage arrays or lists of vectors (in C). Now contrast this function with the constructor for a Vector object : Vector *new_Vector(double x, double y, double z) { Vector *v; v = new Vector(x,y,z); // Call C++ constructor return v; } Both functions return a Vector, but the constructor is returning a brand-new Vector while the other function is returning a Vector that was already created (hopefully). In Perl, both vectors will be indistinguishable—clearly a problem considering that we would probably like the newly created Vector to be destroyed when we are done with it.
To manage these problems, each class contains two methods that access an internal hash table called
This scheme works remarkably well in practice but it isn't foolproof. In fact, it will fail if you create a new C object in Perl, pass it on to a C function that remembers the object, and then destroy the corresponding Perl object (this situation turns out to come up frequently when constructing objects like linked lists and trees). When C takes possession of an object, you can change Perl's ownership by simply deleting the object from the # Perl code to change ownership of an object $v = new Vector(x,y,z); $v->DISOWN();
To acquire ownership of an object, the # Given Perl ownership of a file $u = Vector_get($v); $u->ACQUIRE(); As always, a little care is in order. SWIG does not provide reference counting, garbage collection, or advanced features one might find in sophisticated languages. 28.9.4 Nested ObjectsSuppose that we have a new object that looks like this : struct Particle { Vector r; Vector v; Vector f; int type; }
In this case, the members of the structure are complex objects that have already been encapsulated in a Perl proxy class. To handle these correctly, we use the package Particle; ... %BLESSEDMEMBERS = ( r => `Vector', v => `Vector', f => `Vector', );
When fetching members from the structure, This implementation allows us to operate on nested structures as follows : # Perl access of nested structure $p = new Particle(); $p->{f}->{x} = 0.0; %${$p->{v}} = ( x=>0, y=>0, z=>0); 28.9.5 Proxy FunctionsWhen functions take arguments involving a complex object, it is sometimes necessary to write a proxy function. For example : double dot_product(Vector *v1, Vector *v2); Since Vector is an object already wrapped into a proxy class, we need to modify this function to accept arguments that are given in the form of tied hash tables. This is done by creating a Perl function like this : sub dot_product { my @args = @_; $args[0] = tied(%{$args[0]}); # Get the real pointer values $args[1] = tied(%{$args[1]}); my $result = vectorc::dot_product(@args); return $result; } This function replaces the original function, but operates in an identical manner. 28.9.6 Inheritance
Simple C++ inheritance is handled using the Perl // shapes.i // SWIG interface file for shapes class %module shapes %{ #include "shapes.h" %} class Shape { public: virtual double area() = 0; virtual double perimeter() = 0; void set_location(double x, double y); }; class Circle : public Shape { public: Circle(double radius); ~Circle(); double area(); double perimeter(); }; class Square : public Shape { public: Square(double size); ~Square(); double area(); double perimeter(); } The resulting, Perl wrapper class will create the following code : Package Shape; @ISA = (shapes); ... Package Circle; @ISA = (shapes Shape); ... Package Square; @ISA = (shapes Shape);
The
Since SWIG proxy classes are implemented in Perl, it is easy to subclass from any SWIG generated class. To do this, simply put the name of a SWIG class in the 28.9.7 Modifying the proxy methods
It is possible to override the SWIG generated proxy/shadow methods, using /* Let's make the constructor of the class Square more verbose */ %feature("shadow") Square(double w) %{ sub new { my $pkg = shift; my $self = examplec::new_Square(@_); print STDERR "Constructed an @{[ref($self)]}\n"; bless $self, $pkg if defined($self); } %} class Square { public: Square(double w); ... }; 28.10 Adding additional Perl code
If writing support code in C isn't enough, it is also possible to write code in Perl. This code gets inserted in to the void set_transform(Image *im, double x[4][4]); ... /* Rewrite the high level interface to set_transform */ %perlcode %{ sub set_transform { my ($im, $x) = @_; my $a = new_mat44(); for (my $i = 0; $i < 4, $i++) { for (my $j = 0; $j < 4, $j++) { mat44_set($a, $i, $j, $x->[i][j]) } } example.set_transform($im, $a); free_mat44($a); } %}
In this example, my $a = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]; set_transform($im, $a); 29 SWIG and PHPSWIG supports generating wrappers for PHP5. Support for PHP4 has been removed as of SWIG 1.3.37. The PHP developers are no longer making new PHP4 releases, and won't even be patching critical security issues after 2008-08-08, so it doesn't make much sense for SWIG to continue to support PHP4 at this point. If you need to continue to use PHP4, stick with SWIG 1.3.36. In this chapter, we discuss SWIG's support of PHP. The PHP module was extensively rewritten in release 1.3.26, and support for generating OO wrappers for PHP5 was added in 1.3.30. The PHP module works fairly well, but currently does not implement all the features available in some of the other languages.
In order to use this module, you will need to have a copy of the PHP5 include files to compile the SWIG generated files. If you installed PHP from a binary package, you may need to install a “php-dev” or “php-devel” package for these to be installed. You can find out where these files are by running 29.1 Generating PHP Extensions
To build a PHP extension, run swig using the swig -php example.i
This will produce 3 files example_wrap.c, php_example.h and example.php. The first file,
Swig can generate PHP extensions from C++ libraries as well when given the
The usual (and recommended) way is to build the extension as a separate dynamically loaded module (which is supported by all modern operating systems). You can then specify that this be loaded automatically in It is also possible to rebuild PHP from source so that your module is statically linked into the php executable/library. This is a lot more work, and also requires a full rebuild of PHP to update your module, and it doesn't play nicely with package system. We don't recommend this approach, or provide explicit support for it. 29.1.1 Building a loadable extensionTo build your module as a dynamically loadable extension, use compilation commands like these (if you aren't using GCC, the commands will be different, and there may be some variation between platforms - these commands should at least work for Linux though): gcc `php-config --includes` -fpic -c example_wrap.c gcc -shared example_wrap.o -o example.so 29.1.2 Using PHP Extensions
To test the extension from a PHP script, you need to load it first. You can load it for every script by adding this line the extension=/path/to/modulename.so Alternatively, you can load it explicitly only for scripts which need it by adding this line: dl("/path/to/modulename.so"); // Load the module
to the start of each PHP file. SWIG also generates a php module, which attempts to do the include("example.php"); 29.2 Basic PHP interface
It is important to understand that PHP uses a single global namespace into which all symbols from extension modules are loaded. It is quite possible for names of symbols in one extension module to clash with other symbols unless care is taken to 29.2.1 Constants
These work in much the same way as in C/C++, constants can be defined by using either the normal C pre-processor declarations, or the %module example #define PI 3.14159 %constant int E = 2.71828 you can access the constants in your php script like this, include("example.php"); echo "PI = " . PI . "\n"; echo "E = " . E . "\n"; There are two peculiarities with using constants in PHP. The first is that if you try to use an undeclared constant, it will evaluate to a string set to the constant's name. For example, %module example #define EASY_TO_MISPELL 0 accessed incorrectly in PHP, include("example.php"); if(EASY_TO_MISPEL) { .... } else { .... } will issue a warning about the undeclared constant, but will then evaluate it and turn it into a string ('EASY_TO_MISPEL'), which evaluates to true, rather than the value of the constant which would be false. This is a feature! The second 'feature' is that although constants are case sensitive (by default), you cannot declare a constant twice with alternative cases. E.g., %module example #define TEST Hello #define Test World accessed from PHP, include("example.php"); echo TEST, Test; will output “Hello Test” rather than “Hello World”. This is because internally, all constants are stored in a hash table by their lower case name, so 'TEST' and 'Test' will map to the same hash element ('Test'). But, because we declared them case sensitive, the Zend engine will test if the case matches with the case the constant was declared with first. So, in the example above, the TEST constant was declared first, and will be stored under the hash element 'test'. The 'Test' constant will also map to the same hash element 'test', but will not overwrite it. When called from the script, the TEST constant will again be mapped to the hash element 'test' so the constant will be retrieved. The case will then be checked, and will match up, so the value ('Hello') will be returned. When 'Test' is evaluated, it will also map to the same hash element 'test'. The same constant will be retrieved, this time though the case check will fail as 'Test' != 'TEST'. So PHP will assume that Test is a undeclared constant, and as explained above, will return it as a string set to the constant name ('Test'). Hence the script above will print 'Hello Test'. If they were declared non-case sensitive, the output would be 'Hello Hello', as both point to the same value, without the case test taking place. ( Apologies, this paragraph needs rewriting to make some sense. ) 29.2.2 Global VariablesBecause PHP does not provide a mechanism to intercept access and assignment of global variables, global variables are supported through the use of automatically generated accessor functions. %module example; %inline %{ double seki = 2; void print_seki() { zend_printf("seki is now %f\n",seki); } %} is accessed as follows: include("example.php"); print seki_get(); seki_set( seki_get() * 2); # The C variable is now 4. print seki_get();
SWIG supports global variables of all C datatypes including pointers and complex objects. Additional types can be supported by using the
SWIG honors the At this time SWIG does not support custom accessor methods. 29.2.3 FunctionsC functions are converted into PHP functions. Default/optional arguments are also allowed. An interface file like this : %module example int foo(int a); double bar(double, double b = 3.0); ... Will be accessed in PHP like this : include("example.php"); $a = foo(2); $b = bar(3.5, -1.5); $c = bar(3.5); # Use default argument for 2nd parameter 29.2.4 Overloading
Although PHP does not support overloading functions natively, swig will generate dispatch functions which will use 29.2.5 Pointers and ReferencesPointers to C/C++ objects are represented as PHP resources, rather like MySQL connection handles. There are multiple ways to wrap pointers to simple types. Given the following C method: void add( int *in1, int *in2, int *result);
One can include cpointer.i to generate PHP wrappers to %module example %include "cpointer.i" %pointer_functions(int,intp) void add( int *in1, int *in2, int *result); This will result in the following usage in PHP: <?php include("example.php"); $in1=copy_intp(3); $in2=copy_intp(5); $result=new_intp(); add( $in1, $in2, $result ); echo "The sum " . intp_value($in1) . " + " . intp_value($in2) . " = " . intp_value( $result) . "\n"; ?>
An alternative would be to use the include typemaps.i which defines named typemaps for INPUT, OUTPUT and INOUT variables. One needs to either %module example %include "typemaps.i" void add( int *INPUT, int *INPUT, int *OUTPUT); This will result in the following usage in PHP: <?php include("example.php"); $in1 = 3; $in2 = 5; $result= add($in1,$in2); # Note using variables for the input is unnecessary. echo "The sum $in1 + $in2 = $result\n"; ?> Because PHP has a native concept of reference, it may seem more natural to the PHP developer to use references to pass pointers. To enable this, one needs to include phppointers.i which defines the named typemap REFERENCE. %module example %include "phppointers.i" void add( int *REF, int *REF, int *REF); This will result in the following usage in PHP: <?php include("example.php"); $in1 = 3; $in2 = 5; $result = 0; add(&$in1,&$in2,&$result); echo "The sum $in1 + $in2 = $result\n"; ?>
It is important to note that a php variable which is NULL when passed by reference would end up passing a NULL pointer into the function. In PHP, an unassigned variable (i.e. where the first reference to the variable is not an assignment) is NULL. In the above example, if any of the three variables had not been assigned, a NULL pointer would have been passed into
We chose to allow passing NULL pointers into functions because that is sometimes required in C libraries. A NULL pointer can be created in PHP in a number of ways: by using 29.2.6 Structures and C++ classesSWIG defaults to wrapping C++ structs and classes with PHP classes unless “-noproxy” is specified. For PHP5, a PHP wrapper class is generated which calls a set of flat functions wrapping the C++ class. This interface file %module vector class Vector { public: double x,y,z; Vector(); ~Vector(); double magnitude(); }; struct Complex { double re, im; }; Would be used in the following way from PHP5: <?php require "vector.php"; $v = new Vector(); $v->x = 3; $v->y = 4; $v->z = 5; echo "Magnitude of ($v->x,$v->y,$v->z) = " . $v->magnitude() . "\n"; $v = NULL; # destructor called. $c = new Complex(); $c->re = 0; $c->im = 0; # $c destructor called when $c goes out of scope. ?>
Member variables and methods are accessed using the 29.2.6.1 Using -noproxy
The new_Vector(); Vector_x_set($obj,$d); Vector_x_get($obj); Vector_y_set($obj,$d); Vector_y_get($obj); Vector_z_set($obj,$d); Vector_z_get($obj); Vector_magnitude($obj); new_Complex(); Complex_re_set($obj,$d); Complex_re_get($obj); Complex_im_set($obj,$d); Complex_im_get($obj); 29.2.6.2 Constructors and Destructors
The constructor is called when Because PHP uses reference counting to manage resources, simple assignment of one variable to another such as: $ref = $v;
causes the symbol One can force execution of the copy constructor by using: $o_copy = new Object($o);
Destructors are automatically called when all variables referencing the instance are reassigned or go out of scope. The destructor is not available to be called manually. To force a destructor to be called the programmer can either reassign the variable or call 29.2.6.3 Static Member VariablesStatic member variables in C++ are not wrapped as such in PHP as it does not appear to be possible to intercept accesses to such variables. Therefore, static member variables are wrapped using a class function with the same name, which returns the current value of the class variable. For example %module example class Ko { static int threats; }; would be accessed in PHP as, include("example.php"); echo "There has now been " . Ko::threats() . " threats\n"; To set the static member variable, pass the value as the argument to the class function, e.g. Ko::threats(10); echo "There has now been " . Ko::threats() . " threats\n"; 29.2.6.4 Static Member Functions
Static member functions are supported in PHP using the %module example class Ko { static void threats(); }; would be executed in PHP as, include("example.php"); Ko::threats(); 29.2.7 PHP Pragmas, Startup and Shutdown codeTo place PHP code in the generated “example.php” file one can use the code pragma. The code is inserted after loading the shared object. %module example %pragma(php) code=" # This code is inserted into example.php echo \"example.php execution\\n\"; " Results in the following in “example.php” # This code is inserted into example.php echo "example.php execution\n"; The include pragma is a short cut to add include statements to the example.php file. %module example %pragma(php) code=" include \"include.php\"; " %pragma(php) include="include.php" // equivalent.
The phpinfo pragma inserts code in the %module example; %pragma(php) phpinfo=" zend_printf("An example of PHP support through SWIG\n"); php_info_print_table_start(); php_info_print_table_header(2, \"Directive\", \"Value\"); php_info_print_table_row(2, \"Example support\", \"enabled\"); php_info_print_table_end(); "
To insert code into the %module example; %init { zend_printf("Inserted into PHP_MINIT_FUNCTION\n"); } %minit { zend_printf("Inserted into PHP_MINIT_FUNCTION\n"); }
To insert code into the %module example; %mshutdown { zend_printf("Inserted into PHP_MSHUTDOWN_FUNCTION\n"); }
The 29.3 Cross language polymorphismProxy classes provide a more natural, object-oriented way to access extension classes. As described above, each proxy instance has an associated C++ instance, and method calls to the proxy are passed to the C++ instance transparently via C wrapper functions. This arrangement is asymmetric in the sense that no corresponding mechanism exists to pass method calls down the inheritance chain from C++ to PHP. In particular, if a C++ class has been extended in PHP (by extending the proxy class), these extensions will not be visible from C++ code. Virtual method calls from C++ are thus not able access the lowest implementation in the inheritance chain. Changes have been made to SWIG 1.3.18 to address this problem and make the relationship between C++ classes and proxy classes more symmetric. To achieve this goal, new classes called directors are introduced at the bottom of the C++ inheritance chain. Support for generating PHP classes has been added in SWIG 1.3.40. The job of the directors is to route method calls correctly, either to C++ implementations higher in the inheritance chain or to PHP implementations lower in the inheritance chain. The upshot is that C++ classes can be extended in PHP and from C++ these extensions look exactly like native C++ classes. Neither C++ code nor PHP code needs to know where a particular method is implemented: the combination of proxy classes, director classes, and C wrapper functions takes care of all the cross-language method routing transparently. 29.3.1 Enabling directorsThe director feature is disabled by default. To use directors you must make two changes to the interface file. First, add the “directors” option to the %module directive, like this: %module(directors="1") modulename Without this option no director code will be generated. Second, you must use the %feature(“director”) directive to tell SWIG which classes and methods should get directors. The %feature directive can be applied globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); // generate directors for all virtual methods in class Foo %feature("director") Foo; // generate a director for just Foo::bar() %feature("director") Foo::bar; You can use the %feature(“nodirector”) directive to turn off directors for specific classes or methods. So for example, %feature("director") Foo; %feature("nodirector") Foo::bar; will generate directors for all virtual methods of class Foo except bar(). Directors can also be generated implicitly through inheritance. In the following, class Bar will get a director class that handles the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: Foo(int foo); virtual void one(); virtual void two(); }; class Bar: public Foo { public: virtual void three(); }; then at the PHP side you can define require("mymodule.php"); class MyFoo extends Foo { function one() { print "one from php\n"; } } 29.3.2 Director classes
For each class that has directors enabled, SWIG generates a new class that derives from both the class in question and a special
For simplicity let's ignore the In reality, the “appropriate place” is one of only two possibilities: C++ or PHP. Once this decision is made, the rest is fairly easy. If the correct implementation is in C++, then the lowest implementation of the method in the C++ inheritance chain is called explicitly. If the correct implementation is in PHP, the Zend API is used to call the method of the underlying PHP object (after which the usual virtual method resolution in PHP automatically finds the right implementation). Now how does the director decide which language should handle the method call? The basic rule is to handle the method in PHP, unless there's a good reason not to. The reason for this is simple: PHP has the most “extended” implementation of the method. This assertion is guaranteed, since at a minimum the PHP proxy class implements the method. If the method in question has been extended by a class derived from the proxy class, that extended implementation will execute exactly as it should. If not, the proxy class will route the method call into a C wrapper function, expecting that the method will be resolved in C++. The wrapper will call the virtual method of the C++ instance, and since the director extends this the call will end up right back in the director method. Now comes the “good reason not to” part. If the director method were to blindly call the PHP method again, it would get stuck in an infinite loop. We avoid this situation by adding special code to the C wrapper function that tells the director method to not do this. The C wrapper function compares the called and the declaring class name of the given method. If these are not the same, then the C wrapper function tells the director to resolve the method by calling up the C++ inheritance chain, preventing an infinite loop.
One more point needs to be made about the relationship between director classes and proxy classes. When a proxy class instance is created in PHP, SWIG creates an instance of the original C++ class and assigns it to 29.3.3 Ownership and object destructionMemory management issues are slightly more complicated with directors than for proxy classes alone. PHP instances hold a pointer to the associated C++ director object, and the director in turn holds a pointer back to the PHP object. By default, proxy classes own their C++ director object and take care of deleting it when they are garbage collected.
This relationship can be reversed by calling the special Here is an example: class Foo { public: ... }; class FooContainer { public: void addFoo(Foo *); ... };
$c = new FooContainer(); $a = new Foo(); $a->thisown = 0; $c->addFoo($a); In this example, we are assuming that FooContainer will take care of deleting all the Foo pointers it contains at some point. 29.3.4 Exception unrollingWith directors routing method calls to PHP, and proxies routing them to C++, the handling of exceptions is an important concern. By default, the directors ignore exceptions that occur during method calls that are resolved in PHP. To handle such exceptions correctly, it is necessary to temporarily translate them into C++ exceptions. This can be done with the %feature(“director:except”) directive. The following code should suffice in most cases: %feature("director:except") { if ($error == FAILURE) { throw Swig::DirectorMethodException(); } } This code will check the PHP error state after each method call from a director into PHP, and throw a C++ exception if an error occurred. This exception can be caught in C++ to implement an error handler. Currently no information about the PHP error is stored in the Swig::DirectorMethodException object, but this will likely change in the future.
It may be the case that a method call originates in PHP, travels up to C++ through a proxy class, and then back into PHP via a director method. If an exception occurs in PHP at this point, it would be nice for that exception to find its way back to the original caller. This can be done by combining a normal %exception directive with the %exception { try { $action } catch (Swig::DirectorException &e) { SWIG_fail; } } The class Swig::DirectorException used in this example is actually a base class of Swig::DirectorMethodException, so it will trap this exception. Because the PHP error state is still set when Swig::DirectorMethodException is thrown, PHP will register the exception as soon as the C wrapper function returns. 29.3.5 Overhead and code bloatEnabling directors for a class will generate a new director method for every virtual method in the class' inheritance chain. This alone can generate a lot of code bloat for large hierarchies. Method arguments that require complex conversions to and from target language types can result in large director methods. For this reason it is recommended that you selectively enable directors only for specific classes that are likely to be extended in PHP and used in C++. Compared to classes that do not use directors, the call routing in the director methods does add some overhead. In particular, at least one dynamic cast and one extra function call occurs per method call from PHP. Relative to the speed of PHP execution this is probably completely negligible. For worst case routing, a method call that ultimately resolves in C++ may take one extra detour through PHP in order to ensure that the method does not have an extended PHP implementation. This could result in a noticeable overhead in some cases. Although directors make it natural to mix native C++ objects with PHP objects (as director objects) via a common base class pointer, one should be aware of the obvious fact that method calls to PHP objects will be much slower than calls to C++ objects. This situation can be optimized by selectively enabling director methods (using the %feature directive) for only those methods that are likely to be extended in PHP. 29.3.6 TypemapsTypemaps for input and output of most of the basic types from director classes have been written. These are roughly the reverse of the usual input and output typemaps used by the wrapper code. The typemap operation names are 'directorin', 'directorout', and 'directorargout'. The director code does not currently use any of the other kinds of typemaps. It is not clear at this point which kinds are appropriate and need to be supported. 29.3.7 MiscellaneousDirector typemaps for STL classes are mostly in place, and hence you should be able to use std::string, etc., as you would any other type. 30 SWIG and PikeThis chapter describes SWIG support for Pike. As of this writing, the SWIG Pike module is still under development and is not considered ready for prime time. The Pike module is being developed against the Pike 7.4.10 release and may not be compatible with previous versions of Pike.
This chapter covers most SWIG features, but certain low-level details are covered in less depth than in earlier chapters. At the very least, make sure you read the “SWIG Basics” chapter. 30.1 Preliminaries30.1.1 Running SWIGSuppose that you defined a SWIG module such as the following: %module example %{ #include "example.h" %} int fact(int n);
To build a C extension module for Pike, run SWIG using the $ swig -pike example.i
If you're building a C++ extension, be sure to add the $ swig -c++ -pike example.i
This creates a single source file named
The name of the wrapper file is derived from the name of the input file. For example, if the input file is $ swig -pike -o pseudonym.c example.i 30.1.2 Getting the right header filesIn order to compile the C/C++ wrappers, the compiler needs to know the path to the Pike header files. These files are usually contained in a directory such as /usr/local/pike/7.4.10/include/pike
There doesn't seem to be any way to get Pike itself to reveal the location of these files, so you may need to hunt around for them. You're looking for files with the names 30.1.3 Using your module
To use your module, simply use Pike's $ pike Pike v7.4 release 10 running Hilfe v3.5 (Incremental Pike Frontend) > import example; > fact(4); (1) Result: 24 30.2 Basic C/C++ Mapping30.2.1 Modules
All of the code for a given SWIG module is wrapped into a single Pike module. Since the name of the shared library that implements your module ultimately determines the module's name (as far as Pike is concerned), SWIG's 30.2.2 FunctionsGlobal functions are wrapped as new Pike built-in functions. For example, %module example int fact(int n);
creates a new built-in function > import example; > fact(4); (1) Result: 24 30.2.3 Global variablesGlobal variables are currently wrapped as a pair of of functions, one to get the current value of the variable and another to set it. For example, the declaration %module example double Foo;
will result in two functions, > import example; > Foo_get(); (1) Result: 3.000000 > Foo_set(3.14159); (2) Result: 0 > Foo_get(); (3) Result: 3.141590 30.2.4 Constants and enumerated typesEnumerated types in C/C++ declarations are wrapped as Pike constants, not as Pike enums. 30.2.5 Constructors and Destructors
Constructors are wrapped as 30.2.6 Static MembersSince Pike doesn't support static methods or data for Pike classes, static member functions in your C++ classes are wrapped as regular functions and static member variables are wrapped as pairs of functions (one to get the value of the static member variable, and another to set it). The names of these functions are prepended with the name of the class. For example, given this C++ class declaration: class Shape { public: static void print(); static int nshapes; };
SWIG will generate a 31 SWIG and PythonCaution: This chapter is under repair! This chapter describes SWIG's support of Python. SWIG is compatible with most recent Python versions including Python 3.0 and Python 2.6, as well as older versions dating back to Python 2.0. For the best results, consider using Python 2.3 or newer. This chapter covers most SWIG features, but certain low-level details are covered in less depth than in earlier chapters. At the very least, make sure you read the “SWIG Basics” chapter. 31.1 OverviewTo build Python extension modules, SWIG uses a layered approach in which parts of the extension module are defined in C and other parts are defined in Python. The C layer contains low-level wrappers whereas Python code is used to define high-level features. This layered approach recognizes the fact that certain aspects of extension building are better accomplished in each language (instead of trying to do everything in C or C++). Furthermore, by generating code in both languages, you get a lot more flexibility since you can enhance the extension module with support code in either language. In describing the Python interface, this chapter starts by covering the basics of configuration, compiling, and installing Python modules. Next, the Python interface to common C and C++ programming features is described. Advanced customization features such as typemaps are then described followed by a discussion of low-level implementation details. 31.2 Preliminaries31.2.1 Running SWIGSuppose that you defined a SWIG module such as the following: /* File: example.i */ %module example %{ #define SWIG_FILE_WITH_INIT #include "example.h" %} int fact(int n);
The /* File: example.c */ #include "example.h" int fact(int n) { if (n < 0){ /* This should probably return an error, but this is simpler */ return 0; } if (n == 0) { return 1; } else { /* testing for overflow would be a good idea here */ return n * fact(n-1); } } With the header file: /* File: example.h */ int fact(int n);
To build a Python module, run SWIG using the $ swig -python example.i
If building a C++ extension, add the $ swig -c++ -python example.i
This creates two different files; a C/C++ source file
The name of the wrapper file is derived from the name of the input file. For example, if the input file is The following sections have further practical examples and details on how you might go about compiling and using the generated files. 31.2.2 Using distutilsThe preferred approach to building an extension module for python is to compile it with distutils, which comes with all recent versions of python (Distutils Docs ).
Distutils takes care of making sure that your extension is built with all the correct flags, headers, etc. for the version of Python it is run with. Distutils will compile your extension into a shared object file or DLL (
Here is a sample #!/usr/bin/env python """ setup.py file for SWIG example """ from distutils.core import setup, Extension example_module = Extension('_example', sources=['example_wrap.c', 'example.c'], ) setup (name = 'example', version = '0.1', author = "SWIG Docs", description = """Simple swig example from docs""", ext_modules = [example_module], py_modules = ["example"], )
In this example, the line:
The $ swig -python example.i $ python setup.py build_ext --inplace And a .so, or .pyd or… will be created for you. It will build a version that matches the python that you run the command with. Taking apart the command line:
The distutils have many other features, consult the python distutils docs for details. This same approach works on all platforms if the appropriate compiler is installed. (it can even build extensions to the standard Windows Python using MingGW) 31.2.3 Hand compiling a dynamic moduleWhile the preferred approach to building an extension module is to use the distutils, some people like to integrate building extensions with a larger build system, and thus may wish to compile their modules without the distutils. To do this, you need to compile your program using commands like this (shown for Linux): $ swig -python example.i $ gcc -O2 -fPIC -c example.c $ gcc -O2 -fPIC -c example_wrap.c -I/usr/local/include/python2.5 $ gcc -shared example.o example_wrap.o -o _example.so
The exact commands for doing this vary from platform to platform. However, SWIG tries to guess the right options when it is installed. Therefore, you may want to start with one of the examples in the
When linking the module, the name of the output file has to match the name of the module prefixed by an underscore. If the name of your module is “
Compatibility Note: In SWIG-1.3.13 and earlier releases, module names did not include the leading underscore. This is because modules were normally created as C-only extensions without the extra Python support file (instead, creating Python code was supported as an optional feature). This has been changed in SWIG-1.3.14 and is consistent with other Python extension modules. For example, the 31.2.4 Static linkingAn alternative approach to dynamic linking is to rebuild the Python 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.
The usual procedure for adding a new module to Python involves finding the Python source, adding an entry to the
In earlier versions of SWIG, the %module example %inline %{ extern int fact(int); extern int mod(int, int); extern double My_variable; %} %include "embed.i" // Include code for a static version of Python
The $ swig -python example.i $ gcc example.c example_wrap.c \ -Xlinker -export-dynamic \ -DHAVE_CONFIG_H -I/usr/local/include/python2.1 \ -I/usr/local/lib/python2.1/config \ -L/usr/local/lib/python2.1/config -lpython2.1 -lm -ldl \ -o mypython
You will need to supply the same libraries that were used to build Python the first time. This may include system libraries such as Comment: 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).
Compatibility note: The 31.2.5 Using your module
To use your module, simply use the Python $ python >>> import example >>> example.fact(4) 24 >>> A common error received by first-time users is the following: >>> import example Traceback (most recent call last): File "<stdin>", line 1, in ? File "example.py", line 2, in ? import _example ImportError: No module named _example
If you get this message, it means that you either forgot to compile the wrapper code into an extension module or you didn't give the extension module the right name. Make sure that you compiled the wrappers into a module called Another possible error is the following: >>> import example Traceback (most recent call last): File "<stdin>", line 1, in ? ImportError: dynamic module does not define init function (init_example) >>>
This error is almost always caused when a bad name is given to the shared object file. For example, if you created a file Another common error is something similar to the following: Traceback (most recent call last): File "example.py", line 3, in ? import example ImportError: ./_example.so: undefined symbol: fact 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.
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 Finally, suppose that your extension module is linked with another library like this: $ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \ -o _example.so
If the >>> import example Traceback (most recent call last): File "<stdin>", line 1, in ? ImportError: libfoo.so: cannot open shared object file: No such file or directory >>>
This error is generated because the dynamic linker can't locate the $ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \ -Xlinker -rpath /home/beazley/projects/lib \ -o _example.so
Alternatively, you can set the $ env LD_LIBRARY_PATH=/home/beazley/projects/lib python
Finally, you can use a command such as 31.2.6 Compilation of C++ extensionsCompilation of C++ extensions has traditionally been a tricky problem. Since the Python interpreter is written in C, you need to take steps to make sure C++ is properly initialized and that modules are compiled correctly. This should be a non-issue if you're using distutils, as it takes care of all that for you. The following is included for historical reasons, and in case you need to compile on your own. On most machines, C++ extension modules should be linked using the C++ compiler. For example: $ swig -c++ -python example.i $ g++ -O2 -fPIC -c example.cxx $ g++ -O2 -fPIC -c example_wrap.cxx -I/usr/local/include/python2.5 $ g++ -shared example.o example_wrap.o -o _example.so The -fPIC option tells GCC to generate position-independent code (PIC) which is required for most architectures (it's not vital on x86, but still a good idea as it allows code pages from the library to be shared between processes). Other compilers may need a different option specified instead of -fPIC.
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 $ swig -c++ -python example.i $ CC -c example.cxx $ CC -c example_wrap.cxx -I/usr/local/include/python2.5 $ CC -G example.o example_wrap.o -L/opt/SUNWspro/lib -o _example.so -lCrun Of course, the extra libraries to use are completely non-portable—you will probably need to do some experimentation. Sometimes people have suggested that it is necessary to relink the Python 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 Python.
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 $ 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) 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 Python, 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. 31.2.7 Compiling for 64-bit platformsOn 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. To utilize 64-bits, the Python 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. 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). On the Linux x86_64 platform (Opteron or EM64T), besides of the required compiler option -fPIC discussed above, you will need to be careful about the libraries you link with or the library path you use. In general, a Linux distribution will have two set of libraries, one for native x86_64 programs (under /usr/lib64), and another for 32 bits compatibility (under /usr/lib). Also, the compiler options -m32 and -m64 allow you to choose the desired binary format for your python extension. 31.2.8 Building Python Extensions under Windows
Building a SWIG extension to Python under Windows is roughly similar to the process used with Unix. Using the distutils, it is essentially identical. If you have the same version of the MS compiler that Python was built with (the python2.4 and python2.5 distributed by python.org are built with Visual Studio 2003), the standard As of python2.5, the distutils support building extensions with MingGW out of the box. Following the instruction here: Building Python extensions for Windows with only free tools should get you started. If you need to build it on your own, the following notes are provided: You will need to create a DLL that can be loaded into the interpreter. This section briefly describes the use of SWIG with Microsoft Visual C++. As a starting point, many of SWIG's examples include project files. You might want to take a quick look at these in addition to reading this section. In Developer Studio, SWIG should be invoked as a custom build option. This is usually done as follows:
If all went well, SWIG will be automatically invoked whenever you build your project. Any changes made to the interface file will result in SWIG being automatically executed to produce a new version of the wrapper file.
To run your new Python extension, simply run Python and use the $ python >>> import example >>> print example.fact(4) 24 >>>
If you get an Some users have reported success in building extension modules using Cygwin and other compilers. However, the problem of building usable DLLs with these compilers tends to be rather problematic. For the latest information, you may want to consult the SWIG Wiki. 31.3 A tour of basic C/C++ wrappingBy default, SWIG tries to build a very natural Python interface to your C/C++ code. Functions are wrapped as functions, classes are wrapped as classes, and so forth. This section briefly covers the essential aspects of this wrapping. 31.3.1 Modules
The SWIG 31.3.2 FunctionsGlobal functions are wrapped as new Python built-in functions. For example, %module example int fact(int n);
creates a built-in function >>> import example >>> print example.fact(4) 24 >>> 31.3.3 Global variablesC/C++ global variables are fully supported by SWIG. However, the underlying mechanism is somewhat different than you might expect due to the way that Python assignment works. When you type the following in Python a = 3.4 “a” becomes a name for an object containing the value 3.4. If you later type b = a then “a” and “b” are both names for the object containing the value 3.4. Thus, there is only one object containing 3.4 and “a” and “b” are both names that refer to it. This is quite different than C where a variable name refers to a memory location in which a value is stored (and assignment copies data into that location). Because of this, there is no direct way to map variable assignment in C to variable assignment in Python.
To provide access to C global variables, SWIG creates a special object called ` // SWIG interface file with global variables %module example ... %inline %{ extern int My_variable; extern double density; %} ... Now look at the Python interface: >>> import example >>> # Print out value of a C global variable >>> print example.cvar.My_variable 4 >>> # Set the value of a C global variable >>> example.cvar.density = 0.8442 >>> # Use in a math operation >>> example.cvar.density = example.cvar.density*1.10 If you make an error in variable assignment, you will receive an error message. For example: >>> example.cvar.density = "Hello" Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: C variable 'density (double )' >>>
If a variable is declared as
To make ordinary variables read-only, you can use the %{ extern char *path; %} %immutable; extern char *path; %mutable;
The If you just want to make a specific variable immutable, supply a declaration name. For example: %{ extern char *path; %} %immutable path; ... extern char *path; // Read-only (due to %immutable)
If you would like to access variables using a name other than “ $ swig -python -globals myvar example.i
Some care is in order when importing multiple SWIG modules. If you use the “ 31.3.4 Constants and enums
C/C++ constants are installed as Python objects containing the appropriate value. To create a constant, use #define PI 3.14159 #define VERSION "1.0" enum Beverage { ALE, LAGER, STOUT, PILSNER }; %constant int FOO = 42; %constant const char *path = "/usr/local"; 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.
Note: declarations declared as Constants are not guaranteed to remain constant in Python—the name of the constant could be accidentally reassigned to refer to some other object. Unfortunately, there is no easy way for SWIG to generate code that prevents this. You will just have to be careful. 31.3.5 PointersC/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Here is a rather simple interface: %module example FILE *fopen(const char *filename, const char *mode); int fputs(const char *, FILE *); int fclose(FILE *); When wrapped, you will be able to use the functions in a natural way from Python. For example: >>> import example >>> f = example.fopen("junk","w") >>> example.fputs("Hello World\n", f) >>> example.fclose(f) 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 using an especial python container object: >>> print f <Swig Object at _08a71808_p_FILE>
This pointer value can be freely passed around to different C functions that expect to receive an object of type In older versions of Swig (1.3.22 or older), pointers were represented using a plain string object. If you have an old package that still requires that representation, or you just feel nostalgic, you can always retrieve it by casting the pointer object to a string: >>> print str(f) _c0671108_p_FILE Also, if you need to pass the raw pointer value to some external python library, you can do it by casting the pointer object to an integer: >>> print int(f) 135833352 However, the inverse operation is not possible, i.e., you can't build a Swig pointer object from a raw integer value.
Note also that the '0' or NULL pointer is always represented by >>> example.fclose(None) and that will be equivalent to the following, but not really useful, C code: FILE *f = NULL; fclose(f); As much as you might be inclined to modify a pointer value directly from Python, 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, 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: %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; } %}
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 31.3.6 StructuresIf you wrap a C structure, it is wrapped by a Python class. This provides a very natural interface. For example, struct Vector { double x,y,z; }; is used as follows: >>> v = example.Vector() >>> v.x = 3.5 >>> v.y = 7.2 >>> print v.x, v.y, v.z 7.8 -4.5 0.0 >>> Similar access is provided for unions and the data members of C++ classes.
If you print out the value of >>> print v <C Vector instance at _18e31408_p_Vector>
This object is actually a Python instance that has been wrapped around a pointer to the low-level C structure. This instance doesn't actually do anything–it just serves as a proxy. The pointer to the C object can be found in the the >>> print v.this _18e31408_p_Vector >>> Further details about the Python proxy class are covered a little later.
struct Foo { ... %immutable; int x; /* Read-only members */ char *name; %mutable; ... };
When If a structure contains arrays, access to those arrays is managed through pointers. For example, consider this: struct Bar { int x[16]; }; If accessed in Python, you will see behavior like this: >>> b = example.Bar() >>> print b.x _801861a4_p_int >>>
This pointer can be passed around to functions that expect to receive an >>> c = example.Bar() >>> c.x = b.x # Copy contents of b.x to c.x
For array assignment, SWIG copies the entire contents of the array starting with the data pointed to by 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: struct Foo { int a; }; struct Bar { Foo f; };
Now, suppose that you access the >>> b = Bar() >>> x = b.f
In this case, Bar b; Foo *x = &b->f; /* Points inside b */ Because the pointer points inside the structure, you can modify the contents and everything works just like you would expect. For example: >>> b = Bar() >>> b.f.a = 3 # Modify attribute of structure member >>> x = b.f >>> x.a = 3 # Modifies the same structure 31.3.7 C++ classesC++ classes are wrapped by Python classes as well. For example, if you have this class, class List { public: List(); ~List(); int search(char *item); void insert(char *item); void remove(char *item); char *get(int n); int length; }; you can use it in Python like this: >>> l = example.List() >>> l.insert("Ale") >>> l.insert("Stout") >>> l.insert("Lager") >>> l.get(1) 'Stout' >>> print l.length 3 >>> Class data members are accessed in the same manner as C structures. Static class members present a special problem for Python. Prior to Python-2.2, Python classes had no support for static methods and no version of Python supports static member variables in a manner that SWIG can utilize. Therefore, SWIG generates wrappers that try to work around some of these issues. To illustrate, suppose you have a class like this: class Spam { public: static void foo(); static int bar; }; In Python, the static member can be access in three different ways: >>> example.Spam_foo() # Spam::foo() >>> s = example.Spam() >>> s.foo() # Spam::foo() via an instance >>> example.Spam.foo() # Spam::foo(). Python-2.2 only The first two methods of access are supported in all versions of Python. The last technique is only available in Python-2.2 and later versions.
Static member variables are currently accessed as global variables. This means, they are accessed through >>> print example.cvar.Spam_bar 7 31.3.8 C++ inheritanceSWIG is fully aware of issues related to C++ inheritance. Therefore, if you have classes like this class Foo { ... }; class Bar : public Foo { ... }; those classes are wrapped into a hierarchy of Python classes that reflect the same inheritance structure. All of the usual Python utility functions work normally: >>> b = Bar() >>> instance(b,Foo) 1 >>> issubclass(Bar,Foo) 1 >>> issubclass(Foo,Bar) 0 Furthermore, if you have functions like this void spam(Foo *f);
then the function It is safe to use multiple inheritance with SWIG. 31.3.9 Pointers, references, values, and arraysIn C++, there are many different ways a function might receive and manipulate objects. For example: void spam1(Foo *x); // Pass by pointer void spam2(Foo &x); // Pass by reference void spam3(const Foo &x);// Pass by const reference void spam4(Foo x); // Pass by value void spam5(Foo x[]); // Array of objects In Python, there is no detailed distinction like this–specifically, there are only “objects”. There are no pointers, references, arrays, and so forth. 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: >>> f = Foo() # Create a Foo >>> spam1(f) # Ok. Pointer >>> spam2(f) # Ok. Reference >>> spam3(f) # Ok. Const reference >>> spam4(f) # Ok. Value. >>> spam5(f) # Ok. Array (1 element) Similar behavior occurs for return values. For example, if you had functions like this, Foo *spam6(); Foo &spam7(); Foo spam8(); const Foo &spam9();
then all three functions will return a pointer to some 31.3.10 C++ overloaded functionsC++ overloaded functions, methods, and constructors are mostly supported by SWIG. For example, if you have two functions like this: void foo(int); void foo(char *c); You can use them in Python in a straightforward manner: >>> foo(3) # foo(int) >>> foo("Hello") # foo(char *c) Similarly, if you have a class like this, class Foo { public: Foo(); Foo(const Foo &); ... }; you can write Python code like this: >>> f = Foo() # Create a Foo >>> g = Foo(f) # Copy f Overloading support is not quite as flexible as in C++. Sometimes there are methods that SWIG can't disambiguate. For example: void spam(int); void spam(short); or void foo(Bar *b); void foo(Bar &b); If declarations such as these appear, you will get a warning message like this: example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int) at example.i:11. To fix this, you either need to ignore or rename one of the methods. For example: %rename(spam_short) spam(short); ... void spam(int); void spam(short); // Accessed as spam_short or %ignore spam(short); ... void spam(int); void spam(short); // Ignored 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. Please refer to the “SWIG and C++” chapter for more information about overloading. 31.3.11 C++ operatorsCertain C++ overloaded operators can be handled automatically by SWIG. For example, consider a class like this: 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 Complex &c) const; Complex operator-() const; double re() const { return rpart; } double im() const { return ipart; } }; When wrapped, it works like you expect: >>> c = Complex(3,4) >>> d = Complex(7,8) >>> e = c + d >>> e.re() 10.0 >>> e.im() 12.0 >>> c += d >>> c.re() 10.0 >>> c.im() 12.0 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 class Complex { ... friend Complex operator+(double, const Complex &c); ... }; then SWIG 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: %rename(Complex_add_dc) operator+(double, const Complex &);
There are ways to make this operator appear as part of the class using the Also, be aware that certain operators don't map cleanly to Python. For instance, overloaded assignment operators don't map to Python semantics and will be ignored. 31.3.12 C++ namespacesSWIG 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, %module example namespace foo { int fact(int n); struct Vector { double x,y,z; }; }; it works in Python as follows: >>> import example >>> example.fact(3) 6 >>> v = example.Vector() >>> v.x = 3.4 >>> print v.y 0.0 >>>
If your program has more than one namespace, name conflicts (if any) can be resolved using %rename(Bar_spam) Bar::spam; namespace Foo { int spam(); } namespace Bar { int spam(); } 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. 31.3.13 C++ templates
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 %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>; In Python: >>> import example >>> p = example.pairii(3,4) >>> p.first 3 >>> p.second 4 Obviously, there is more to template wrapping than shown in this example. More details can be found in the SWIG and C++ chapter. Some more complicated examples will appear later. 31.3.14 C++ Smart Pointers
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 template<class T> class SmartPtr { ... T *operator->(); ... } Then, if you have a class like this, class Foo { public: int x; int bar(); }; A smart pointer would be used in C++ as follows: SmartPtr<Foo> p = CreateFoo(); // Created somehow (not shown) ... p->x = 3; // Foo::x int y = p->bar(); // Foo::bar
To wrap this in Python, simply tell SWIG about the %module example ... %template(SmartPtrFoo) SmartPtr<Foo>; ... Now, in Python, everything should just “work”: >>> p = example.CreateFoo() # Create a smart-pointer somehow >>> p.x = 3 # Foo::x |