Swig

SWIG , or Simplified Wrapper and Interface Generator, by Dave Beazley, generates Tcl C interfaces C and C++ code.

Attributes

name
SWIG
website
http://www.swig.org/
latest version
3.0.12

See Also

Swig example showing access to C structures from Tcl
Generating wrappers for C and Fortran

Documentation

Using SWIG to interface scripting languages with C/C++ (alternate ), Pramode C.E. and Gopakumar C.E, 2000
Tcl and SWIG as a C/C++ Development Tool , David Beazley, 1998
SWIG Extends Scripting Languages , David Beazley, Dr.Dobb's , 1998-02-01
SWIG Examples

Description

SWIG automates the generation of interfaces in various languages, including Tcl, to functions written in C/C++. SWIG reads ANSI C/C++ declarations and builds a an interface in the target language. SWIG is avalable for Unix-like systems and also for Windows

The idea of Swig is to provide a tool that can, with hopefully little pain, allow one to create glue code between general libraries and various scripting languages, one of which is Tcl. Swig can be used for C++ or C libraries - making it one of the first places people are recommended to look when dealing with legacy libraries.

Benefits and uses of SWIG:

  • Rapidly prototype new features.
  • Interactively debug and test your code.
  • Develop a graphical user interface.
  • Saves lots of time--allowing you to work on the real problem.

To contrast SWIG with Objectify - SWIG has you prepare a small interface file that specifies what functions are to be wrapped, rather than adding macros to your original header file. It also works with C, as well as C++.

If you look around in books or places like Cameron Laird's Tcl pages [L1 ] you can find a lot of information about integrating Tcl with C. That's all fine and dandy if you're going to write the interface code by hand.

But if you want a nice example of how you ought to write your wrappers to call C or C++ from Tcl, then you can't go wrong looking at the code generated by SWIG. David Beazley did a great job of implementing both the old Tcl 7.x all-string interface and the Tcl 8.x object interface. Modern versions of SWIG (since 1.3a5) do not support the Tcl 7.x interface.

For example, a short little function like this:

double convert ( int *value, char *targetUnits );

gets wrapped by SWIG with this code for Tcl 8.x:

static int _wrap_convert(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {

        double  _result;
        int * _arg0;
        char * _arg1;
        Tcl_Obj * tcl_result;
        char * rettype;
        int templength;

        clientData = clientData; objv = objv;
        tcl_result = Tcl_GetObjResult(interp);
        if ((objc < 3) || (objc > 3)) {
                Tcl_SetStringObj(tcl_result,"Wrong # args. convert value targetUnits ",-1);
                return TCL_ERROR;
        }
        if ((rettype = SWIG_GetPointerObj(interp,objv[1],(void **) &_arg0,"_int_p"))) {
                Tcl_SetStringObj(tcl_result, "Type error in argument 1 of convert. Expected _int_p, received ", -1);
                Tcl_AppendToObj(tcl_result, rettype, -1);
                return TCL_ERROR;
        }
        if ((_arg1 = Tcl_GetStringFromObj(objv[2], &templength)) == NULL) return TCL_ERROR;
        _result = (double )convert(_arg0,_arg1);
        tcl_result = Tcl_GetObjResult(interp);
        Tcl_SetDoubleObj(tcl_result,(double) _result);
        return TCL_OK;
}

If you're using SWIG 1.1 or earlier, it also supported the 7.x interface model:

static int _wrap_convert(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {

        double  _result;
        int * _arg0;
        char * _arg1;

        clientData = clientData; argv = argv;
        if ((argc < 3) || (argc > 3)) {
                Tcl_SetResult(interp, "Wrong # args. convert value targetUnits ",TCL_STATIC);
                return TCL_ERROR;
        }
        if (SWIG_GetPtr(argv[1],(void **) &_arg0,"_int_p")) {
                Tcl_SetResult(interp, "Type error in argument 1 of convert. Expected _int_p, received ", TCL_STATIC);
                Tcl_AppendResult(interp, argv[1], (char *) NULL);
                return TCL_ERROR;
        }
        _arg1 = argv[2];
        _result = (double )convert(_arg0,_arg1);
        Tcl_PrintDouble(interp,(double) _result, interp->result);
        return TCL_OK;
}

As of SWIG 1.3.40, the generated C/C++ wrapper will use the Stubs feature if compiled with -DUSE_TK_STUBS. Also, you can override the minimum version to support which is passed to Tcl_InitStubs() and Tk_InitStubs() with -DSWIG_TCL_STUBS_VERSION="8.3" or the version being compiled with using -DSWIG_TCL_STUBS_VERSION=TCL_VERSION.


AMG: I'd like the ability to unload a Swig extension, but the latest CVS only provides xxx_Init() and xxx_SafeInit(). Any suggestions?


2011-04-13: David Beazley: "... life is too short to wrap my brain around the ever-growing pile of hacks called C++. ... things like this are why I don't work on swig anymore."