There are 3 files here. They are "simple.c", "simple.tk", and "makefile". This example creates a new Tk_Main and Tcl_AppInit. This example strips lots of extra code out of Tk_Main, and allows a cleaner startup of your own C + Tk application. This example will compile for Tk4.1/Tcl7.5 and Tk8.0+/Tcl8.0+. This example illustrates a method of creating a GUI with Tk that will work with your C application. It illustrates the sharing of variables between C and Tk, and a method of registering your own C commands to call from Tk. To try this example: Create a new directory for these files. Cut each section and save with the correct name. Edit and execute the makefile. It will work without too much trouble. The file simple.tk will fail to execute if the end of lines aren't UNIX end of lines. Double check them if you have problems. Execute in the background by simply typing: simple & -----------------cut and name file "simple.c"---------------------------- /* * Copyright :) * Michael K. Ganley * mikegan@world.std.com * 20 January 1997 * Simple C + Tk example */ #include #include #include #include typedef int (Tcl_myAppInitProc) _ANSI_ARGS_((int argc, char **argv, Tcl_Interp *interp )); void Tk_myMain _ANSI_ARGS_((int argc, char **argv, Tcl_myAppInitProc *appInitProc)); int Tcl_myAppInit _ANSI_ARGS_((int argc, char **argv, Tcl_Interp *interp )); int getSumExampleCmd _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **)); static Tcl_Interp *interp; static int alive = 1; /* * * main -- * */ main(int argc, char *argv[]) { Tk_myMain( argc, argv, Tcl_myAppInit); return(0); } /* * * Tk_myMain ---- * */ void Tk_myMain( int argc, char **argv, Tcl_myAppInitProc *myappInitProc ) { Tcl_FindExecutable( argv[0] ); interp = Tcl_CreateInterp(); if( ( *myappInitProc )( argc, argv, interp ) != TCL_OK ) { fprintf( stderr, "\nUnexpected application error!" ); } Tcl_Exit(0); } /* * * Tcl_myAppInit -- * */ int Tcl_myAppInit( int argc, char *argv[], Tcl_Interp *interp ) { int retcode; Tk_Window mainWindow; int share2 = 0; if( Tcl_Init(interp) == TCL_ERROR ) { fprintf(stderr, "Tcl_Init failed: %s\n", interp->result); exit(1); } if( Tk_Init(interp) == TCL_ERROR ) { fprintf(stderr, "Tk_Init failed: %s\n", interp->result); exit(1); } /* register your own commands */ Tcl_CreateCommand( interp, "getSumExample", getSumExampleCmd, (ClientData) NULL, (void (*) ()) NULL); mainWindow = Tk_MainWindow(interp); Tcl_LinkVar( interp, "alive", ( char * )&alive, TCL_LINK_INT ); Tcl_LinkVar( interp, "share2", ( char * )&share2, TCL_LINK_INT ); retcode = Tcl_EvalFile( interp, "simple.tk" ); if(retcode != TCL_OK) { fprintf(stderr, "\nGUI: Initialization ERROR: "); fprintf(stderr, "%s\n", interp->result); exit(1); } /* main loop */ do { Tcl_DoOneEvent(TK_DONT_WAIT); /* illustrate activity occuring between C and GUI */ share2++; if( share2 == 1000000 ) { share2 = 0; } } while( alive == 1 ); return 0; } /* * * Get sum example command * */ int getSumExampleCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)) { double var1; double var2; /* get passed parameters to sum */ if( Tcl_GetDouble( interp, argv[1], &var1 ) != TCL_OK ) { return TCL_ERROR; } if( Tcl_GetDouble( interp, argv[2], &var2 ) != TCL_OK ) { return TCL_ERROR; } sprintf( interp->result, "%f", var1+var2 ); return TCL_OK ; } ------------------------------------------------------------------------- -----------------cut and name file "simple.tk"---------------------------- # # Super simple example of Tk + C # Tcl/Tk script file # Michael K. Ganley # mikegan@world.std.com # 20 January 1997 # option add *Entry.cursor gumby option add *Button.highlightThickness 0 option add *Frame.highlightThickness 0 option add *Entry.highlightThickness 0 option add *Button.borderWidth 1 # # configTop # Procedure to show toplevel window and set some attributes # proc configTop {} { global color global tkVersion global tk_strictMotif wm positionfrom . user wm sizefrom . program wm geometry . 320x100+20+10 wm maxsize . 400 300 wm minsize . 100 100 wm title . {Ganley's "simple2" example} . configure -background $color(bg) } # # main Tk procedure # proc mainProc {} { global color global fonts global alive global var global share2 button .kill \ -bg $color(bg) \ -text {Quit} \ -font $fonts(2) \ -command {set alive 0} button .add \ -bg $color(bg) \ -text {Add} \ -font $fonts(2) \ -command {addProc} entry .e1 \ -relief {flat} \ -bg $color(bg2) \ -font $fonts(2) \ -textvariable var(1) entry .e2 \ -relief {flat} \ -bg $color(bg2) \ -font $fonts(2) \ -textvariable var(2) entry .e3 \ -relief {flat} \ -bg $color(bg) \ -font $fonts(2) \ -textvariable var(3) \ -state disabled entry .e4 \ -relief {flat} \ -bg $color(bg) \ -font $fonts(2) \ -textvariable share2 \ -state disabled place .kill -x 5 -y 5 -width 100 -height 20 -anchor nw place .add -x 5 -y 30 -width 100 -height 20 -anchor nw place .e1 -x 110 -y 30 -width 50 -height 20 -anchor nw place .e2 -x 162 -y 30 -width 50 -height 20 -anchor nw place .e3 -x 215 -y 30 -width 50 -height 20 -anchor nw place .e4 -x 5 -y 55 -width 50 -height 20 -anchor nw } # # Add variables by calling C function # proc addProc {} { global var set result [getSumExample $var(1) $var(2)] set temp [format "%-.3f" $result] set var(3) "= $temp" } # # Initialize variables # proc initGlobals {} { global color global fonts global alive global var global share2 set color(bg) gray70 set color(bg2) gray50 set fonts(2) "-Adobe-Helvetica-medium-R-Normal--*-100-*" set alive 1 set var(1) 0.0 set var(2) 0.0 } # # Read C's shared variable "share2" every half second # And schedule other stuff if you desire # proc running {} { global share2 # force update of e4's textvariable set share2 $share2 after 500 [ list running ] } # # Invoke to begin # initGlobals configTop mainProc running # eof # ------------------------------------------------------------------------- -----------------cut and name file "makefile" --------------------------- # Makefile # Change of paths may be needed - no specific compiler options # may need some tweeking for your system. # # Michael K. Ganley # mikegan@world.std.com # 20 January 1997 # # # You may replace the *.so stuff with *.a stuff instead # if you have all of the *.a libraries. CC = gcc -g LINKER = $(CC) LIBS = /usr/lib/libtk.so \ /usr/lib/libtcl.so \ /usr/X11R6/lib/libX11.so # -ldl is needed for *.so libraries. LLIBS = -ltk -ltcl -lm -ldl # Flags CFLAGS = -I/usr/local/include \ -I/usr/X11/include \ -I/usr/src/tk \ -I/usr/src/tcl COFLAGS = -q LDFLAGS = -I/usr/X11/include \ -I/usr/src/tk \ -I/usr/src/tcl all: simple simple: simple.o libtk.so $(CC) -o simple simple.o $(LDFLAGS) $(LIBS) $(LLIBS) libtk.so : clean: rm -f simple *.o -------------------------------------------------------------------------