By this point, you should have a pretty decent understanding of the underlying philosophy of Tcl and Tk, and the whole concept of extensions, of which [incr Tcl] and PLplot are examples. These alone are enough to allow the rapid prototyping and development of powerful, flexible graphical applications. Normally the programmer simply writes a shell script to be executed by the Tk windowing shell, wish. It is in vogue for each Tcl/Tk extension package to build it's own “extended WISH”. There are many examples of this, and indeed even PLplot's plserver program, described in an earlier chapter, could just as easily have been called plwish.
In any event, as exciting and useful as these standalone, extended windowing shells may be, they are ultimately only the beginning of what you can do. The real benefit of this approach is realized when you make your own “extended WISH”, comprised of Tcl, Tk, any of the standard extensions you like, and finally embellished with a smattering of application specific extensions designed to support your own application domain. In this section we give a detailed introduction to the process of constructing your own WISH. After that, you're on your own...
The standard way to make your own WISH, as supported by the Tcl/Tk
system, is to take a boilerplate file,
tkAppInit.c
, edit to reflect the Tcl/Tk
extensions you will be requiring, add some commands to the
interpreter, and link it all together.
Here for example is the important part of the
tk02
demo, extracted from the file
xtk02.c
, which is effectively the extended
WISH definition file for the tk02
demo.
Comments and other miscellany are omitted.
#include "tk.h" #include "itcl.h" /* ... */ int myplotCmd (ClientData, Tcl_Interp *, int, char **); int Tcl_AppInit(interp) Tcl_Interp *interp; /* Interpreter for application. */ { int plFrameCmd (ClientData, Tcl_Interp *, int, char **); Tk_Window main; main = Tk_MainWindow(interp); /* * Call the init procedures for included packages. Each call should * look like this: * * if (Mod_Init(interp) == TCL_ERROR) { * return TCL_ERROR; * } * * where "Mod" is the name of the module. */ if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Itcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Pltk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } /* * Call Tcl_CreateCommand for application-specific commands, if * they weren't already created by the init procedures called above. */ Tcl_CreateCommand(interp, "myplot", myplotCmd, (ClientData) main, (void (*)(ClientData)) NULL); /* * Specify a user-specific start up file to invoke if the * application is run interactively. Typically the start up * file is "~/.apprc" where "app" is the name of the application. * If this line is deleted then no user-specific start up file * will be run under any conditions. */ tcl_RcFileName = "~/.wishrc"; return TCL_OK; } /* ... myPlotCmd, etc ... */
The calls to Tcl_Init()
and
Tk_Init()
are in every WISH. To make an
extended WISH, you add calls to the initialization routines for any
extension packages you want to use, in this [incr Tcl]
(Itcl_Init()
) and PLplot
(Pltk_Init()
). Finally you add keywords to the
interpreter, associating them with functions in your code using
Tcl_CreateCommand()
as shown.
In particular, PLplot has a number of [incr Tcl] classes in its Tcl library. If you want to be able to use those in your WISH, you need to include the initialization of [incr Tcl].
Having constructed your Tcl_AppInit()
function,
you now merely need to link this file with your own private files
to provide the code for any functions you registered via
Tcl_CreateCommand()
(and any they depend on),
against the Tcl, Tk and extension libraries you are using.
cc -c tkAppInit.c cc -c mycommands.c cc -o my_wish tkAppInit.o mycommands.o -lplplotftk -ltcl -ltk -litcl -lX11 -lm
Add any needed -L
options as needed.
Voila! You have made a wish.
Now you are ready to put the genie to work. The basic plan here is to write shell scripts which use your new application specific windowing shell as their interpreter, to implement X Windows user interfaces to control and utilize the facilities made available in your extensions.
Effectively this just comes down to writing Tcl/Tk code, embellished as appropriate with calls to the extension commands you registered. Additionally, since this wish includes the PLplot extensions, you can instantiate any of the PLplot family of [incr Tcl] classes, and invoke methods on those objects to effect the drawing of graphs. Similarly, you may have your extension commands (which are coded in C) call the PLplot C programmers API to draw into the widget. In this way you can have the best of both worlds. Use compiled C code when the computational demands require the speed of compiled code, or use Tcl when your programming convenience is more important than raw speed.