This note describes how I combined Visual-Tcl (VTCL), with mktclapp, under ms visual c/c++ (version 6) so that I could use all the visual c tools/debugger etc. and produce a program with a GUI that was not specific to windows or Unix - in fact ports pretty easily (the GUI part that is). And the result is (usually) a single executable file that does not need external .tcl files to read at runtime; they end up getting built in. There are numerous possibilities, this note just talks about setting up a simple case to use with visual c/c++. (I assume the reader is familiar with visual tcl and mktclapp. If not, read them first; perhaps play with visual tcl so you can build the small example I describe below.) What follows is a rough, but hopefully useful guide for others. It is written from the PC perspective. Since the tools described were designed for Unix, there are descriptions and tutorials that describe how to do that under Unix. The only gotcha seems to be to be careful when transferring files; get the line terminators right, if you mess up, as I've done, you can get strange results, as the \ at the end of a line can end up with a trailing character that tcl does not like. Otherwise, it's pretty straightforward. Perhaps someone can craft an appwizzard that would setup the project in one easy step. --------------------------------------------------- Step 0a. Install tcl/tk (I used version Tcl/Tk 8.2 for Windows, Binary Distribution) Important notes from the readme file therein: The official home for Tcl and Tk on the Web is at: http://www.scriptics.com The binary release is distributed as a self-extracting archive called tcl82.exe. I ran this and installed all items, including headers and lib files. I installed into the default location (c:\program files\tcl) 0b. Also, need to acquire visual tcl (I use version 1.20) that installed simply by unzipping into a directory of my choice got from http://www.neuron.com/stewart/vtcl/ 0c. And need xmktclapp got from http://www.hwaci.com/sw/mktclapp/ There are two parts here. A tcl GUI on top of a command line utility. xmktclapp.tcl is the GUI, it just runs (either wish it or double click) mktclapp.c is a C program (in a single .c file) that I built as a console task. I did have to use the /Zm800 option to allow for the huge imbedded strings in this program (lots of tcl code). I then placed this executable in my path, i.e. somewhere that it can be found by command line. The name of this is mktclapp.exe, and I put it into the tcl/bin directory and also in c:\windows, it found it in one of them; I don't remember which. This is needed to handle the custom build step in visual c, and also to run xmktclapp.tcl's build step. You can also put it into the same directory where the project lives. You should take some time to read the html docs, they are quite good. 0d. Of course: Install vc++ as usual. --------------------------------------------------- Step 1. Using visual c++ 6.0 create a new project (Win32 console application, empty project, finish). Any name is ok, this creates a new directory with a few files and a debug folder. --------------------------------------------------- Step 2. Copy the file xmktclapp.tcl into the new directory just created, i.e. in the directory where the project.dsw and .dsp files live. Find it from explorer, and double click it (if tcl is installed properly, it will run), exit for now without saving changes. --------------------------------------------------- Step 3. Create an empty file tcl_c_code.c or some such in the same project dir. I right click and select new text file, which I then rename - ignore warning about changing the extension. (.c is mandatory, if you want c++ you're on you're own) Next, create a minimal myapp.tcl (see below). This file is the output from the visual tcl program, To create a very simple one button vtcl file: run visual tcl, ( you should know how to use this, try their tutorial first) select new, click in the top-level window and then add a button by clicking the toolbar (b) rename the new button to exit, double click it to attach tcl code and enter one line of "exit" (w/o the quotes) save as myapp.tcl in the directory where everything else is. you can exit visual tcl for now --------------------------------------------------- Step 4. configure xmktclapp (once) now run xmktclapp.tcl by double clicking it. a. In the settings tab: It looks for .mta type files (which there are none - good) and defaults to appinit.mta for its configuration file, Change that to myapp.mta and in the output c file box put myapp.c (myapp is anything you want, but the name must agree with other myapp.* used here and later). I also set all options to no/none except app-mode which I set to tcl/tk b. the libraries tab should show this if you installed in the default place, leave it: C:/PROGRAM FILES/TCL/lib/tcl8.2 C:/PROGRAM FILES/TCL/lib/tk8.2 c. c/c++ modules tab: push the insert button and select the file tcl_c_code.c d. tcl scripts tab: likewise, push insert and choose myapp.tcl set the startup script to myapp.tcl also. (use browse to find it or just type it into the entry field) Go back to settings tab, push the build button (save config also makes sense now too) it should tell you it built myapp.c and myapp.h with no errors. NOTE::If it says cannot find program or something similar, then you most likely forgot about the mktclapp.exe program. See below for more info on building it. Then make sure its path-find-able. quit xmktclapp now (file/exit), and myapp.mta plus myapp.c and myapp.h should also appear in the directory. This step won't need to be repeated unless you want to add additional settings here. If you do, then you need to study the docs that came with xmktclapp. Either way, the .h file is only created once, and whenever the myapp.tcl file changes (when you change something in visual tcl and do a save) visual C will notice and run the mktclapp.exe program to generate a new myapp.c file. Making this automatic is described below. ------------------ Step 5. configure your visual c project: Add 2 files (select fileview, expand, right click source files, add files) myapp.c & tcl_c_code.c into the source folder, (tcl_c_code.c is still empty but myapp.c should have lots of stuff, created in step 4). Add a workspace folder called tcl, use tcl for name and extension (right click project name at top, select new folder, set both entry boxes to tcl) right click the new tcl folder and select add files, change file type to all files and find the file myapp.tcl and add it. Now find myapp.tcl in the workspace (under the tcl folder) and right click and choose settings. go to custom build and Put the following 2 lines into commands: echo "mktclapp -f $(WkspDir)\$(InputName).mta >$(WkspDir)\$(InputName).c" mktclapp -f "$(WkspDir)\$(InputName).mta" >"$(WkspDir)\$(InputName).c" (you can copy/paste from this but remove leading spaces) The echo line is optional but useful if the WkspDir etc. expansions didn't work for some reason. Put this into outputs: $(ProjDir)\$(InputName).c Create a lib folder, like the tcl folder or use any existing folder to add two .lib files as follows: Choose insert files into project and locate (in ...tcl/lib) tcl82.lib and tk82.lib (not the stub files, I don't know what they are for) (you may need to navigate a bit here, and choose .lib for file types) mine were found in C:\Program Files\Tcl\lib\ Setup the include directory: Right click source files, then settings, then change settings to all configurations go to c/c++ and preprocessor, and add to additional include directories the location of the include files mine is: c:\program files\tcl\include Now push the save all button in visual c. Ok, now try to do a rebuild all, and you should be able to run the program. You may need to build twice, my system seems to need this sometimes. Just hit F7 until all is built. NOTE::: if you get an error running the custom build step, you probably did not build the mktclapp program. Or maybe you forgot to put the mktclapp.exe in a path-find-able location. Remember, to build the mktclapp program, create a console project, find the mktclapp.c file, put it in the project directory then add it. You may also need to type /Zm800 into the project options (select the project name, not the source file, you can't enter command line options for specific files, only for the entire project) Try setting some breakpoints, or try building with browse info etc. It should all work just fine. There's a main program in myapp.c that you can step through a bit. Later you can do simply a "build", it will detect which files need to be re-compiled (the .tcl is handled by the mktclapp custom build step). It will tell you that myapp.c has been changed externally, which is ok. Sometimes, you might need to hit the build button a second time. You can debug the program as usual. I've not had any particular problems, other than the tcl window does not get updated while stepping through code, but hey, did you expect that? See below example on a workaround to this. --------------------------------------------------------- ADVANCED: Ok, now let's add some C code that will be executed when you push a button and have that C code do some tcl/tk stuff. Go into visual tcl, and add a button. Let it default to the name of button. Double click the button and add the command mybutton hello there Also, VERY IMPORTANT, add the alias name for this button to be button1. (select the new button, type alt-a or use the menu) enter button1 the alias will appear after you click away from and then back to the button save the visual tcl file (you can exit or not, I leave mine minimized as I build up more visual stuff, but I have 2 screens to use and lots o memory) in Visual C, add the below code into tcl_c_code.c (which is currently empty) OH, btw, don't create any tcl callable c routines with names like "button" or anything else that tcl/tk expects to be a reserved name. I did that and got very long error dialog boxes!!! Prefix everything with "my" or whatever. ------------------------------------------------------- #include #include #include #include "myapp.h" int do_tkupdate(int z) { // optional, handy routine while (Tk_DoOneEvent(TK_ALL_EVENTS | TK_DONT_WAIT)) { z++; } return z; // ignore, I was just curious about this } // note you must read mktclapp to understand the below code // but ET_TCLARGS defines the argc, argv like a unix command line // below creates a tcl callable c routine "mybutton" int ET_COMMAND_mybutton(ET_TCLARGS){ int i; printf("Button: number of args = %d for %s\n",argc,argv[0]); for ( i=1 ; i < argc ; i++) { printf("arg %d = (%s)\n",i,argv[i]); } Et_GlobalEvalF(Et_Interp , "$widget(button1) configure -background red"); do_tkupdate(0); return TCL_OK; } ---------------------------------------------------------- This code defines 2 procedures. The first, do_tkupdate is optional, but I find very convenient. It causes things to get updated immediately, instead of waiting until my procedures return. (But I don't use this in a scrollbar callback, it got into a recursive loop!!!) The second one retrieves its arguments and prints them into the visual c console window, and then it executes a tcl command to color the new button red. Note the use of the $widget(button1) which is how one connects to the visual tcl button's alias. Ok, now rebuild all or build. You should get a warning that myapp.c has changed, just say ok. Go (f5) You should see your window. Press button, it should turn red and the args will be listed in the debug console window. (If you have a tcl console you don't want, you can go back and change that in the xmktclapp program, it's a setting on the first panel) The debug console is from visual c/c++. Note there is a small issue here of dependencies. Say you change the tcl_c_code.c code by adding a new routine that is callable by tcl. You then do a build, only the .c file is recompiled. You need to also force the mktclapp to run, with a build all or just compile the myapp.tcl code. The mktclapp.exe program needs to scan your c code to determine how to build a table of all c routines that are callable from tcl. So, there is a dependency here that is not correctly handled. But it is rare that you add a new tcl callable routine, and if you do, just remember to rebuild all. You could also add tcl_c_code.c to the dependency list of myapp.tcl, but then every change to myapp.c would cause mktclapp to run and it would create a new myapp.c producing an annoying message that myapp.c has changed and ask if you want to reload it (even though it probably has not really changed). Your choice however. Oh, btw, when you run a console program (by double clicking it from the desktop) it will have a console window that you might not want. You can create a shortcut to the program, and set the startup window to be minimized during the run. This window will get all the stdout and stderr stuff. ------------------------------------------------------------- Enjoy! Eric Taylor et@rocketship.com