Extending SWIG

Caution: This chapter is being rewritten! (11/25/01)

Introduction

This chapter describes SWIG's internal organization and the process by which new target languages can be developed. First, a brief word of warning---SWIG has been undergoing a massive redevelopment effort that has focused extensively on its internal organization. The information in this chapter is mostly up to date, but changes are ongoing. Expect to find a few inconsistencies.

Prerequisites

In order to extend SWIG, it is useful to have the following background:

High Level Overview

When you run SWIG on an interface, processing is handled in stages by a few different system components:

Preprocessing

The role of the preprocessor needs to be strongly emphasized. In practice, a lot of SWIG's processing and internal configuration is managed not by code written in C, but by configuration files in the SWIG library. In fact, when you run SWIG, parsing starts with a small interface file like this (note: this explains the cryptic error messages that users sometimes get when SWIG is misconfigured or installed incorrectly):
%include "swig.swg"             // Global SWIG configuration
%include "langconfig.swg"       // Language specific configuration
%include "yourinterface.i"      // Your interface file
The swig.swg file contains global configuration information. In addition, this file defines many of SWIG's standard directives as macros. For instance, an excerpt of of swig.swg looks like this:
...
/* Code insertion directives such as %wrapper %{ ... %} */

#define %init        %insert("init")
#define %wrapper     %insert("wrapper")
#define %header      %insert("header")
#define %runtime     %insert("runtime")

/* Access control directives */

#define %readonly    %pragma(swig) readonly;
#define %readwrite   %pragma(swig) readwrite;

/* Directives for callback functions */

#define %callback(x) %pragma(swig) callback=`x`;
#define %nocallback  %pragma(swig) nocallback;

/* Directives for attribute functions */

#define %attributefunc(_x,_y)  %pragma(swig)   attributefunction=`_x`":"`_y`;
#define %noattributefunc       %pragma(swig)   noattributefunction;

/* %ignore directive */

#define %ignore         %rename($ignore)
#define %ignorewarn(x)  %rename("$ignore:" x)

/* Generation of default constructors/destructors */

#define %nodefault     %pragma nodefault
#define %makedefault   %pragma makedefault

...
The fact that most of the standard SWIG directives are macros is intended to simplify the implementation of the parser. For instance, rather than having to support dozens of special grammar rules, it is easier to have a few basic primitives such as %pragma or %insert.

The langconfig.swg file is supplied by the target language. This file contains language-specific configuration information. More often than not, this file provides run-time wrapper support code (e.g., the type-checker) as well as a collection of typemaps that define the default wrapping behavior.

Although the SWIG preprocessor is intended to mimic the behavior of the C preprocessor, it is not meant to be a direct replacement. Instead, its behavior is adapted for use with SWIG and it provides a number of a non-standard extensions:

As a debugging aide, the text that SWIG feeds to its C++ parser can be obtained by running swig -E interface.i. This output probably isn't too useful in general, but it will show how macros have been expanded as well as everything else that goes into the low-level construction of the wrapper code.

Parsing

The current C++ parser handles a subset of C++. Most incompatibilities with C are due to subtle aspects of how SWIG parses declarations. Specifically, SWIG expects all C/C++ declarations to follow this general form:
storage type declarator initializer;
storage is a keyword such as extern, static, typedef, or virtual. type is a primitive datatype such as int or void. type may be optionally qualified with a qualifier such as const or volatile. declarator is a name with additional type-construction modifiers attached to it (pointers, arrays, references, functions, etc.). Examples of declarators include *x, **x, x[20], and (*x)(int,double). The initializer may be a value assigned using = or body of code enclosed in braces { ... }.

This declaration format covers most common C++ declarations. However, the C++ standard is somewhat more flexible in the placement of the pieces. For example, it is technically legal, although unusual form to write something like int typedef const a in your program. SWIG simply doesn't bother to deal with this (although it could probably be modified if there is sufficient demand).

The other significant difference between C++ and SWIG is in the treatment of typenames. In C++, if you have a declaration like this,

int blah(Foo *x, Bar *y);
it won't parse correctly unless Foo and Bar have been previously defined as types either using a class definition or a typedef. The reasons for this are subtle, but this treatment of typenames is normally integrated at the level of the C tokenizer---when a typename appears, a different token is returned to the parser instead of an identifier.

SWIG does not operate in this manner--any legal identifier can be used as a type name. The reason for this is primarily motivated by the use of SWIG with partially defined data. Specifically, I wanted to make SWIG easy to use on interfaces with missing type information. On a more practical level however, the introduction of typenames would greatly complicate other parts of SWIG such as the parsing of SWIG directives (many of which also rely upon identifier names).

Because of the different treatment of typenames, the most serious limitation of the SWIG parser is that it can't process declarations in which an extra (and unnecessary) grouping operator is used. For example:

int (x);         /* A variable x */
int (y)(int);    /* A function y */
The parser is also unable to handle declarations with no return type or bare argument names. For example, in an old C program, you might see things like this:
foo(a,b) {
...
}
In this case, the return type as well as the types of the arguments are taken to be an int. However, SWIG interprets the above code as an abstract declarator for a function returning a foo and taking types a and b as arguments).

Parse Trees

The SWIG parser produces a complete parse tree of the input file before any wrapper code is actually generated. Each item in the tree is known as a "Node". Each node is identified by a symbolic tag. Furthermore, a node may have an arbitrary number of children. The parse tree structure and tag names of an interface can be displayed using swig -dump_tags. For example:
$ swig -c++ -python -dump_tags example.i
 . top (example.i:1)
 . top . include (example.i:1)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/swig.swg:71)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/swig.swg:71)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/swig.swg:83)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/swig.swg:83)
 . top . include (example.i:4)
 . top . include . insert (/r0/beazley/Projects/lib/swig1.3/python/python.swg:7)
 . top . include . insert (/r0/beazley/Projects/lib/swig1.3/python/python.swg:8)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:19)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:19)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:19)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:20)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:20)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:20)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:21)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:21)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:21)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:22)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:22)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:22)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:23)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:23)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:24)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:24)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:25)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:25)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:26)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:26)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:29)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:29)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:32)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:32)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:42)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:42)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:42)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:42)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:45)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:45)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:46)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:46)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:49)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:49)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:59)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:61)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:61)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:61)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:62)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:62)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:63)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:63)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:66)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:66)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:66)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:66)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:69)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:69)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:72)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:72)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:75)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:75)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:75)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:84)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:84)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:105)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:114)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:114)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:114)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:124)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:124)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:137)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:137)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:154)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:154)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:164)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:164)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:173)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:173)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:173)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:182)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:182)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:191)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:191)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:200)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:200)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:205)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:208)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:208)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:208)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:211)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:211)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:211)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:214)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:214)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:214)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:214)
 . top . include . typemap (/r0/beazley/Projects/lib/swig1.3/python/python.swg:217)
 . top . include . typemap . typemapitem (/r0/beazley/Projects/lib/swig1.3/python/python.swg:217)
 . top . include (example.i:6)
 . top . include . module (example.i:2)
 . top . include . insert (example.i:6)
 . top . include . include (example.i:9)
 . top . include . include . class (example.h:3)
 . top . include . include . class . access (example.h:4)
 . top . include . include . class . constructor (example.h:7)
 . top . include . include . class . destructor (example.h:10)
 . top . include . include . class . cdecl (example.h:11)
 . top . include . include . class . cdecl (example.h:11)
 . top . include . include . class . cdecl (example.h:12)
 . top . include . include . class . cdecl (example.h:13)
 . top . include . include . class . cdecl (example.h:14)
 . top . include . include . class . cdecl (example.h:15)
 . top . include . include . class (example.h:18)
 . top . include . include . class . access (example.h:19)
 . top . include . include . class . cdecl (example.h:20)
 . top . include . include . class . access (example.h:21)
 . top . include . include . class . constructor (example.h:22)
 . top . include . include . class . cdecl (example.h:23)
 . top . include . include . class . cdecl (example.h:24)
 . top . include . include . class (example.h:27)
 . top . include . include . class . access (example.h:28)
 . top . include . include . class . cdecl (example.h:29)
 . top . include . include . class . access (example.h:30)
 . top . include . include . class . constructor (example.h:31)
 . top . include . include . class . cdecl (example.h:32)
 . top . include . include . class . cdecl (example.h:33)
Even for the most simple interface, the parse tree structure is larger than you might expect. For example, in the above output, a substantial number of nodes are actually generated by the python.swg configuration file which defines typemaps and other directives. The contents of the user-supplied input file don't appear until the end of the output.

The contents of each parse tree node consist of a collection of attribute/value pairs. Internally, the nodes are simply stored as a hash table. A display of the parse-tree structure can be obtained using swig -dump_tree. For example:

$ swig -c++ -python -dump_tree example.i
...
      +++ include ----------------------------------------
      | name         - "example.i"

            +++ module ----------------------------------------
            | name         - "example"
            | 
            +++ insert ----------------------------------------
            | code         - "\n#include \"example.h\"\n"
            | 
            +++ include ----------------------------------------
            | name         - "example.h"

                  +++ class ----------------------------------------
                  | abstract     - "1"
                  | sym:name     - "Shape"
                  | name         - "Shape"
                  | kind         - "class"
                  | symtab       - 0x40194140
                  | sym:symtab   - 0x40191078

                        +++ access ----------------------------------------
                        | kind         - "public"
                        | 
                        +++ constructor ----------------------------------------
                        | sym:name     - "Shape"
                        | name         - "Shape"
                        | decl         - "f()."
                        | code         - "{\n    nshapes++;\n  }"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ destructor ----------------------------------------
                        | sym:name     - "~Shape"
                        | name         - "~Shape"
                        | storage      - "virtual"
                        | code         - "{\n    nshapes--;\n  }"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "x"
                        | name         - "x"
                        | decl         - ""
                        | type         - "double"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "y"
                        | name         - "y"
                        | decl         - ""
                        | type         - "double"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "move"
                        | name         - "move"
                        | decl         - "f(double,double)."
                        | parms        - double ,double 
                        | type         - "void"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "area"
                        | name         - "area"
                        | decl         - "f(void)."
                        | parms        - void 
                        | storage      - "virtual"
                        | value        - "0"
                        | type         - "double"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "perimeter"
                        | name         - "perimeter"
                        | decl         - "f(void)."
                        | parms        - void 
                        | storage      - "virtual"
                        | value        - "0"
                        | type         - "double"
                        | sym:symtab   - 0x40194140
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "nshapes"
                        | name         - "nshapes"
                        | decl         - ""
                        | storage      - "static"
                        | type         - "int"
                        | sym:symtab   - 0x40194140
                        | 
                  +++ class ----------------------------------------
                  | sym:name     - "Circle"
                  | name         - "Circle"
                  | kind         - "class"
                  | bases        - 0x40194510
                  | symtab       - 0x40194538
                  | sym:symtab   - 0x40191078

                        +++ access ----------------------------------------
                        | kind         - "private"
                        | 
                        +++ cdecl ----------------------------------------
                        | name         - "radius"
                        | decl         - ""
                        | type         - "double"
                        | 
                        +++ access ----------------------------------------
                        | kind         - "public"
                        | 
                        +++ constructor ----------------------------------------
                        | sym:name     - "Circle"
                        | name         - "Circle"
                        | parms        - double 
                        | decl         - "f(double)."
                        | code         - "{ }"
                        | sym:symtab   - 0x40194538
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "area"
                        | name         - "area"
                        | decl         - "f(void)."
                        | parms        - void 
                        | storage      - "virtual"
                        | type         - "double"
                        | sym:symtab   - 0x40194538
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "perimeter"
                        | name         - "perimeter"
                        | decl         - "f(void)."
                        | parms        - void 
                        | storage      - "virtual"
                        | type         - "double"
                        | sym:symtab   - 0x40194538
                        | 
                  +++ class ----------------------------------------
                  | sym:name     - "Square"
                  | name         - "Square"
                  | kind         - "class"
                  | bases        - 0x40194760
                  | symtab       - 0x40194788
                  | sym:symtab   - 0x40191078

                        +++ access ----------------------------------------
                        | kind         - "private"
                        | 
                        +++ cdecl ----------------------------------------
                        | name         - "width"
                        | decl         - ""
                        | type         - "double"
                        | 
                        +++ access ----------------------------------------
                        | kind         - "public"
                        | 
                        +++ constructor ----------------------------------------
                        | sym:name     - "Square"
                        | name         - "Square"
                        | parms        - double 
                        | decl         - "f(double)."
                        | code         - "{ }"
                        | sym:symtab   - 0x40194788
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "area"
                        | name         - "area"
                        | decl         - "f(void)."
                        | parms        - void 
                        | storage      - "virtual"
                        | type         - "double"
                        | sym:symtab   - 0x40194788
                        | 
                        +++ cdecl ----------------------------------------
                        | sym:name     - "perimeter"
                        | name         - "perimeter"
                        | decl         - "f(void)."
                        | parms        - void 
                        | storage      - "virtual"
                        | type         - "double"
                        | sym:symtab   - 0x40194788

Code Generation

Language modules work by attaching handler functions to different types of parse-tree nodes. These handlers simply look at the attributes of each node in order to produce low-level code.

However, the picture is actually a little more complicated than this. In certain cases, parse tree nodes are transformed.


SWIG 1.3 - Last Modified : November 25, 2001