back to lofibucket.com

Why

Ok so you want to embed a scripting language in your application. For some strange reason, you do not want to use Lua. So, you figure out Tcl is the way to go, but sadly the online documentation is full of holy wars and pretty hard to read overall. Here’s some directions to get you started on Windows 7 using Microsoft Visual Studio 2010.

Building Tcl

Getting the source

First you need to fetch the source files, in this case the latest stable version is tcl861-src.zip. Extract the zip contents to a neat place, because we will instruct MSVC to load some libraries from there later on.

Compilation

Fire up Visual Studio 2010, and open the command prompt (Tools > Visual Studio Command Prompt). Navigate to the tcl\win directory you extracted earlier. Now you can build Tcl with nmake.

For example, to build the debug DLL (tcl86g.dll) with no threading support type

c:\cdev\sdk\tcl\win>nmake -f makefile.vc core MACHINE=IX86 OPTS=msvcrt,nothreads,symbols

See makefile.vc for configuration options.

Using Tcl in your project

From the project properties under the VC++ Directories-section add the Tcl build directory to your library paths. In my case I added tcl\win\Debug_VC10 to the list. Note that the library path will be different in Debug and Release builds.

After that add tcl\generic to your Include Directories so you can include tcl.h in your source files.

The directories on the project property page.

The directories on the project property page.

Linking

In order for the compiler to automatically use your new compiled DLL you need to link against tcl86g.lib. Add tcl86g.lib (or just tcl86.dll in Release-mode) to Linker > Input > Additional Dependencies

When running the executable you of course need to have the tcl86g.dll in the same place with the executable. During the development phase it’s enough to drop the dll to the project directory though.

Testing

You can try your project with the following code adapted from StackOverflow

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <tcl.h>

int main(int argc, char**argv)
{
    printf("Running script...\n");

    Tcl_Interp *interp;
    int code;
    char *result;

    Tcl_FindExecutable(argv[0]);
    interp = Tcl_CreateInterp();
    code = Tcl_Eval(interp, "source myscript.tcl; init");

    /* Retrieve the result... */
    result = Tcl_GetString(Tcl_GetObjResult(interp));

    /* Check for error! If an error, message is result. */
    if (code == TCL_ERROR) {
    fprintf(stderr, "ERROR in script: %s\n", result);
    exit(1);
    }

    /* Print (normal) result if non-empty; we'll skip handling encodings for now */
    if (strlen(result)) {
    printf("%s\n", result);
    }

    /* Clean up */
    Tcl_DeleteInterp(interp);
    exit(0);
}

The code calls init-proc defined in myscript.tcl

Read more