Building a fully-compiled, standalone C program from Tcl/Tk and C code involves 3 basic steps:
The specifics given below are based on the source code and makefiles for sdr and confcntlr-v0.4. The .tcl files used in the explanation below are: uimain.tcl, ctrlmenu.tcl (from confcntlr-v0.4 source code), and libs.tcl (created by the Makefile).
tcl2c tcl_uimain < uimain.tcl > tcl_uimain.c
tcl2c tcl_ctrlmenu < ctrlmenu.tcl > tcl_ctrlmenu.c
UI_FILES = tcl_libs.o tcl_uimain.o tcl_ctrlmenu.oTK_LIBRARY_FILES = $(LIBRARY_TCL)/init.tcl \
$(LIBRARY_TK)/tk.tcl \
$(LIBRARY_TK)/bgerror.tcl \
$(LIBRARY_TK)/button.tcl \
$(LIBRARY_TK)/entry.tcl \
$(LIBRARY_TK)/focus.tcl \
$(LIBRARY_TK)/listbox.tcl \
$(LIBRARY_TK)/menu.tcl \
$(LIBRARY_TK)/palette.tcl \
$(LIBRARY_TK)/scale.tcl \
$(LIBRARY_TK)/tearoff.tcl \
$(LIBRARY_TK)/text.tcl \
$(LIBRARY_TK)/optMenu.tcl $(LIBRARY_TK)/scrlbar.tcl(I omitted ($LIBRARY_TK)/dialog.tcl because I wrote my own procedure.)
# Make a .c file from a .tcl file: use the .tcl file being processed
# ($<) as input to tcl2c but rename it so that the filename without
# the extension is used with "tcl_" prepended (tcl_$*)
# Create the object files.tcl_%.c: %.tcl rm -f $@; ./tcl2c tcl_$* < $< > $@
# Create the concatenated list of standard .tcl files and remove # lines with "source"; redirect the output to "libs.tcl".tcl_%.o: tcl_%.c $(CC) -c $< libs.tcl: $(TK_LIBRARY_FILES) cat $(TK_LIBRARY_FILES) | sed '/^[ ]*source[ ]/d' > libs.tcl
-- Declare global character arrays for each of the .c files created from .tcl files:
extern const char tcl_libs[], tcl_uimain[], tcl_ctrlmenu[];-- Declare global variables for the main window and Tcl interpreter:
static Tk_Window mainWin;-- Inside main():
Tcl_Interp *interp;
delete the call: Tk_Main();-- Inside Tcl_AppInit():
add this code:
#ifdef WIN32 extern int TkPlatformInit(Tcl_Interp *interp); TkSetPlatformInit(TkPlatformInit); #endif
add this code: interp = Tcl_CreateInterp(); Tcl_AppInit(interp); Tk_MainLoop();
delete the call to Tcl_Init;
KEEP THE CALL to Tk_Init()!
If not needed, delete the call to Tcl_StaticPackage();
add the following code:
mainWin = Tk_MainWindow(interp);
#ifdef WIN32 { extern int WinPutsCmd(ClientData, Tcl_Interp*, int, char **); Tcl_CreateCommand(interp,"puts",WinPutsCmd,0,0); } #endif Add the Tcl_CreateCommand() statements for any Tcl commands that your C code will call.
Add: Tcl_VarEval(interp, tcl_libs, 0);
This will evaluate the TK_LIBRARY_FILES. Do NOT use Tcl_Eval().Add: Tcl_Eval() or Tcl_VarEval() statements for each of the C strings created for your own Tcl scripts; e.g., Tcl_VarEval(interp, tcl_uimain, 0); Tcl_VarEval(interp, tcl_ctrlmenu, 0);
Copy the tkUnixInit.c file from the Tcl/Tk installation (or the file in the sdr or confcntlr source code). This has the TkPlatformInit() function. And, of course, include this file in your source code.