Integration of TCL / TK and C procedures, introduction
Comparing the fast and easy development graphic support interface provided by TCL / TK, the X program is very cumbersome. TCL / TK is a scripting language, just like some other scripting languages, there are many things that cannot be done or difficult. The solution is to develop together with TCL / TK. The TCL / TK system provides an interpreter for C program call TCL / TK to run the TCL / TK script. The supplied library includes a method of initializing a variable, calling different scripts and access variables. Use these mixed variables also provide benefits to their accessible features. Simple callback and time functions allow programmers to make events, and register a C function to be a TCL / TK process capability to become a powerful tool. This document covers some basic knowledge of TCL / TK scripts and integration. The Compile Option section describes the variable library and contains the necessary files for the creation. Initializing and the Registration Command section explains how to start, how to call C functions from the TCL / TK script, the last part of the access variables explain how to read and write TCL / TK variables from the C function.
Second, the compilation option
In order to access the TCL / TK library, you must set some regular routines and compile it in your source code. There are two headers with two call libraries are declared. #Include
Third, initialization and registration command
Establish a mix of mixed TCL / TK & C applications to surround several selection commands. The first is the "TK_MAIN" function, which is used to control the entire TCL / TK interpreter program. This command does not return a value, so it needs to be added to your "main" function, once you initialize all programs, "TK_MAIN" function brings three variables. The second variable is a string type array, and each string has a special meaning. The first variable represents the number of elements in this array. The third variable is a pointer to the initialization function. This initialization function is executed in many places. The string array notifies the name of the Tcl / TK interpreter application via "TK_Main" and the location of the TCL / TK command in the script. This array is actually a command line parameter for the interpreter. The first item of the array gives the application name, and the second item gives the running script location. If the script is not in the same execution directory, you need a full path. Due to inherited reasons, TCL / TK requires strings to modify in many functions. It also has a function of function scope, avoiding these problems the earliest ways to pass the code fragment below the dynamic allocation string, showing calls to use "Hello World" The application and script "Hello.tcl" call "TK_MAIN". // prototype for the initialization functionint InitProc (Tcl_Interp * interp); // declare an array for two stringschar * ppszArg [2]; // allocate strings and set their contentsppszArg [0] = (char *) malloc (sizeof (char) * 12); ppszarg [1] = (char *) malloc (sizeof (char) * 12); struffpy (ppszarg [0], "hello world"); strcpy (ppszarg [1], "./hello.tcl" ); // the folload (2, ppszarg, initproc); Initialization function "TK_MAIN" call controls your program over the Tcl / TK, but after the bottom initialization and the TCL / TK script runs Before, you can perform user-defined functions. The above example shows this type of function: "initproc". User-defined initialization functions must return an integer type and generate a parameter TCL_INTERP * of the interpreter. Establish an actual interpreter in the initialization function to call "TK_INIT". The "TK_INIT" function sets a parameter to the interpreter, which is the pointer that passes to the initialization function. The following code is only the initialization function, and more is listed later. INT IRPROC (TCL_INTERP * InterP) {INT IRET; // Initialize TkfirstiRet = TK_INIT (InterP); if (IRet! = TCL_OK) {FPRINTF (stderr, "unable to initialize tk! / n"); return (IRET); } // end ifreturn (TCL_OK);} // end initproc
C Functions As the TCL / TK process now you have to be familiar with the process call in the TCL / TK script. The process calls the C function when the design hybrid application is used. Complete it needs to call the "TCL_CREATECOMMAND" function. This is a common practice in the initialization function. The call function is like calling other processes during the TCL / TK process. There is no need to declare this process in the TCL / TK script. The function registration has a specific prototype process. They must return an integer type and set up 4 variables, the first is the TCL / TK library file type "ClientData". The second variable is a pointer to the interpreter. The last two variables are similar to "Argc" and "Argv" in the C "MAIN" function being used to pass parameters to the TCL / TK process. The parameter "argc" contains a number of "Argv" that passes to the TCL / TK process is a string array, and each string contains a parameter. INT Myfunc (ClientData Data, TCL_INTERP * PINTERP, INT ARGC, CHAR * Argv []); When a function is registered as a TCL / TK process, you need to contact it when using it, the pointer passes the "ClientData". The concept of "clientData" allows programmers to contact data structure and objects, and calls the process that can reference this object. This structure does not often need. The "TCL_CREATECOMMAND" function is called like a registration process mentioned earlier. This function has 5 parameters. The first parameter is a pointer to the interpreter. The second parameter is the process name in the Tcl / Tk, and the third parameter is a pointer to the function, which is called when the TCL / TK process is executed. The last two parameters are "clientData" items, a pointer delete routine. It allows the C function to be called when the program exits for the structure of the contacted object. Pointer "ClientData" pointing to the delete function is not frequently called. Below is the TCL / TK process call "hey_there" to call an example of "MyFunc" declared above. Tcl_createCommand (Interp, "Hey_There", MyFunc, (ClientData) NULL, (TCL_CMDDELETEPROC *) NULL); Variable Access When performing a TCL / TK process, call C functions and allow you to get TCL / TK from C, in order to Gets help in TCL / TK, which has a range of functions, which contain information and settings for processing from the TCL / TK variable.
The TCL_GETVAR "TCL_GETVAR" function returns a string pointer to the TCL / TK variable. This function has three parameters: pointing to the interpreter's pointer, the name of the Tcl / TK variable, a flag Flag. This variable is accessed in the current scope of the execution script to the interpreter. If you don't have local variables at the current range, you will access global variables. Returns an error if there is no matching global variable. The Flags parameter allows you to specify TCL_GLOBAL_ONLY, in order to enable this function to access the global variable of this variable name, the following is part of the code accessed in the Tcl / TK script. SET SAY_HELLO_TO "World" The following code is to access the TCL / TK variable "SAY_HELLO_TO" .Char shelloto [30]; // after this call shelloto Should Contain "World" strncpy (shelloto, Tcl_Getvar (Pinterp, "Say_hello_to", 0), 29);
The TCL_SETVAR "TCL_SETVAR" function allows the programmer to modify the value of the TCL / TK variable. This function has four parameters: the first is the interpreter pointer, the second is the TCL / TK variable name to modify the value, the third is the new value to modify, the last one is the TCL / TK flag Flags. The flag of "TCL_SETVAR" flags is the same as "TCL_Getvar". The "TCL_SETVAR" function returns a NULL value when the error is encountered during the setting. If the variable does not exist, this function will establish a new variable within the script referenced by the interpreter pointer. The following code will set the value of the TCL / TK variable "Say_hello_to" "World". Tcl_setvar (Pinterp, "Say_hello_to", "World", 0); Example of Integrated C & TCL / TK Applications This application demonstrates the basis required to integrate C and TCL / TK. This app shows a range of login boxes and buttons. When the information is pressed from the login box input and buttons, the other airspace is also updated. This has many interfaces that share the memory device, which is a way to call large applications. This interface requires the header file below without being included, so it is impossible to compile this application. But reading this is not a bad example.
The Makefilethe Script File: Pr1THE C File: Proof.c #! /. Software / local / .admin / bins / bin / wish -f # ===================== ================================================ # xmail # by Christopher Trudeau, CopyRight 1997 ## This tcl / tk script displays a desktop clock which goes inverse video when # new mail arrives. A pull down menu allows the user to launch remote login # sessions on servers specified in the "hosts" variable. The sessions have # the appropriate "xhost "and" DISPLAY "values. ## Comments and criticism on this program are greatly appreciated. Feel free to # send me a note at ctrudeau@etude.uwaterloo.ca. This material is copyright # but non-commercial institutes have permission to reproduce The Program in # its entirety, all iv users required of the # author. # ================================ ============================== # ------------------- ----------------------------------------- # Global Settings # ----- -------------------------------------------------- ---- # Fill in The Fol Lowing List for hosts in wish to access, spaces or tabs # seprating the names of the hosts; eg: ## set hosts "ampere etude watt.uwaterloo.ca" set hosts "ampere watt ohm morse novice"
# ------------------------------------------------- ----------- # Procedures # ------------------------------------ ------------------------- # Proc PrrefreshDisplay - Called Periodically to Refresh The Displayed Time and # status of the mail boxproc pradedisplay {} {global last # Get the TimeSet I [EXEC DATE] Set i [String Range $ I 11 15] # Get The Mailbox StatusCatch {[EXEC FRM -Q -S New]} Mailif {[String First "no" $ mail] == -1} {# "You have new mail." Results in white on black.ltime configure -fg white -bg black -text $ i # if first Time set, do the double beep thingif {$ last == 0} {Bellafter 120bell} set Last 1} else {# "YOU HAVE NO New Mail." Results in black on white.ltime configure -fg black -bg white -text $ ist last 0} # -------------- -------------------------------------------------- # Main code # ---------------------------------------------- -------------- # Create the main window and place it if specifiedwm title. "Xmail" set args [lindex $ argv 0] String Trim $ args -if {$ args == "geometry"} {WM geometry. [Lindex $ argv 1]} # figure out what terminal name we are atset username [exec whoami] set temp [String First $] set temp [string first $ userName $ termName] set termName [string range $ termName $ temp end] set temp [string first ($ termName] set temp2 [string first) $ termName] set termName [string range $ termName $ temp $ temp2] set termName [string trim $ Termname "()"] # itialize variables and widgetsset Last 0Set Font "- * - * - Medium-r-NORMAL - * - 120 - * - * - * - * - * - *" SET FONT2 "- * - * -MEDIUM-R-NORMAL - * - 100 - * - * - * - * - * - * "Label .ltime -font $ font # create the menu buttonMenubutton .mmenu-text">
"-Menu .mmenu.mmenu .mmenu.m -tearoff 0.mmenu.m add cascade -Label" xterms "-menu .mmenu.m.xterms # create the submenu" xterms "menu .mmenu.m.xterms -Tearoff 0.mmenu.m.xterms Add command -Label "local" -command {exec xim -title local &} set count 0set Hostn [Lindex $ HOSTS $ COUNT] while {$ hostn! = "{Catch {EXEC XHOST $ Hostn} set cmd "Exec RSH $ Hostn xterm -display $ TERMNAME: 0 -Title $ Hostn &". MMenu.m.xterms Add Command -Label $ Hostn -Command $ CMDINCR Count 1Set Hostn [Lindex $ Hosts $ COUNT]}. MMenu.m address - label "exit" -command eXitPack .ltPrrefreshDisplay # ------------------------------------------------------------------------------------------------------------------ ------------------------------------ cc = gccdepend = MAKEDEPENDTCL_DIR = /software/tcl-7.4tk_dir = /software/tk-4.0incs = -i $ (tcl_dir) / include -i $ (tk_dir) / include -i / software / x11r5_dev / incruDelibs = -L / SOFTWARE / X11R5_DEV / LIB -L $ (TCL_DIR) / lib - L $ (tk_dir) / libcccccflags = $ (incs) $ (libs) -g -walllflags = -ltk -ltcl -lx11 -lsocket -lmalldefines = -ddebug.suffixes: .c .o .cpp.co: $ (cc) $ (ccflags) $ <. CPP.O: G -g -wall $ (all defines) -c $ *. cppppproof_c = proof.cproof_o = proof. Oall: Proofproof: $ (Proof_o) $ (CCFLAGS) $ @ $ (proof_o) $ (lflags) Clean: RM -F * .o Proof Corepend :: $ (Depend) -S "# Do not delete"
- $ (allDefines) - $ (proof_c) # do not delete this lineproof.o: /usr/include/stdio.h /usr/include/stdlib.h /usr/include/stdlib.h /usr/include/string.h /usr/include/tcl.hproof.o: /usr/include/tk.h /usr/include/stddef.h /usr/include/sys/types.hproof.o: / usr / Include/Sys/isa_defs.h /usr/include/sys/machtypes.hproof.o: /usr/include/unistd.h /usr/include/sys/unistd.h ../pbx2.hproof.o: / usr / Include/Sys/IPC.H /USR/include/sys/msg.h /usr/include/sys/shm.hproof.o: /usr/include/sys/time.h /usr/include/errno.hproof. O: /usr/include/sys/rrno.h /usr/include/signal.hproof.o: /usr/include/sys/signal.h ../he2.h# !/.software/local/.admin/ BINS / BIN / WISH -F # =========================================== ================= # pr1 # by christopher trudeau, Copyright 1997 ## THIS TCL / TK SCRIPT IS Used in Conjunction with Proof.c to Test The Hardware # emulator for the SX4 Project. ## Comments and criticism on this program is # send me a note at ctrudeau@etude.uwaterloo .ca. This material is copyright # but non-commercial institutes have permission to reproduce the program in # its entirety, all other uses require explicit written permission of the # author. # ============= =============================================== wm Title. "
Proof "# =============================================================================== ============= # main window declarations # ================================ ============================ # Create the frames for Each Row of entry Fieldsfor {set i 0} {$ I <16} { Incr i 1} {frame .f ($ i) Pack .f ($ i)} Button .bdoall -relief raised -text "do all" -command {cmddoit 1} Button .bdoit -relief raised -text "do it" -command {cmdddoit 0} Button .bexit -relief raised -text "death" -command eXitpack .bdoall .bdoit .bexit -in .f (15) -side left # create the mf sender rowsfor {set i 6} {$ i <8} {INCR I 1} {Label .lmfs ($ I) -Text "MFS $ I" Entry .emfs ($ I) -width 4 -TextVariable Entrymfs ($ i) Label .lmfstrunk ($ i) -Text " Trunk: "Entry .emfstrunk ($ I) - Width 4 - TEXTVARIABLE Entrymfstrunk ($ I) Label .lmfschan ($ I) -Text" Chan: "Entry .emfschan ($ I) -Width 4 -TextVariable Entrymfschan ($ I) Pack .LMFS ($ i) .emfs ($ I) .lmfstrunk ($ I) .emfstrunk ($ I) .lmfschan ($ I) /.EMFSCHAN ($ I) -in .f ([expr {$ I - 6 }]) - Side Left} # Create The Trunk Rowsfor {Set i 8} {$ I <16} {Incr i 1} {Label .ltrunk ($ I) - TRUNK $ I "Entry. Estry. Estry. - TEXTVARIABLE Entrytrunk ($ I) Label .ltrunkcard ($ I) -Text" Card: "
Entry. etrunkcard ($ I) - WIDTH 4 - TEXTVARIABLE Entrytrunkcard ($ i) Label .ltrunkchan ($ i) - TEXT "CHAN:" Entry. Estylunkchan ($ I) - WIDTH 4 - TXTVARIABLE Entrytrunkchan ($ I) set j [ EXPR {$ I - 6}] Pack .ltrunk ($ I). Etrunk ($ I) .ltrunkcard ($ I). Etrunkcard ($ I) /.LTRUNKCHAN ($ I). Etrunkchan ($ I) -in .f ($ J) - --SIDE LEFT} # create the mf receiver rowsfor {set i 16} {$ I <20} {INCR i 1} {label .lmfr ($ i) -text "MFR $ I" Entry .emfr ($ i) -width 4 -TextVariable EntrymFR ($ I) set j [expr {$ I - 5}] Pack .LMFR ($ i) .emfr ($ i) -in .f ($ j) -side left} # -------------------------------------------------- ------- // ----------------------------------------- ------------------ // Proof.c // by Christopher Trudeau, Copyright 1997 //// This File Contains the c code to attach to the tcl / tk script ' pr1 'and // to execute CU like operations on the trunk equipment.//// Comments and criticism on this program are greatly appreciated. Feel free // to send me a note at ctrudeau@etude.uwaterloo.ca. This material is // Copyright But Non-Commercial Insti TUTES HAVE Permissions To Reproduce The // Program in ITIRETY, All Other Uses Require Explicit Written // Permission of the Author.////-------------------- ---------------------------------------- // incrude files # include
Int cmddoit (ClientData ClientData, TCL_INTERP * PINTERP, INT ARGC, Char * Argv []); // -------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------- int main () {char * ppszarg [2]; int IMEMID; Printf ("Starting Proof ... / n "); // Get Pointer to Shared Interface Memoryimemid = Shmget (ifmem_key, sizeof (struct ifmem_t), 0644); ifmem_p = (Struct IFMEM_T *) SHMAT (IMEMID, 0, 0); IF ((( INT) {Printf ("error: unable to access shared interface memory / n"); exit (0);} // end if - failed to get interface memory // initialize arguments for tk_mainppszarg [0 ] = (char *) Malloc (SizeOf (Char) * 8); ppszarg [1] = (char *) Malloc (sizeof (char) * 65); struffpy (ppszarg [0], "proof"); strcpy (Ppszarg [1], "/ Home3 / Ctrudeau / S / TCl / ProOF / PR1"); Printf ("Executing TCL / TK Script / N"); TK_MAIN (2, Ppszarg, Initproc); Return (0);} // End main // ---------------------------------------------- ------------- INT IRPROC (TCL_INTERP * Interp) {INT IRET; // Initialize Tk FirstIRet = TK_INIT (InterP); if (IRET! = TCL_OK) {Printf ("Unable to Initialize TK! / N"); Return (IRET);} // end if // register any new TCL / TK Commandstcl_createCommand (Interp, "CMDDoIT", cmddoit, (ClientData) NULL, (TCL_CMDDELETEPROC *) NULL ); return (TCL_OK);} // end initproc // ------------------------------------ ----------------------- // cmddoit //// t c c c i it is is is is is is is is quest ipuened when // user PUSHES The "do it"
button. Each of the entry fields is checked // for their contents and the interface memory is updated accordingly.// The update to i / f mem is used to make connections between various cards // and to put values into those cards (digits , Loop Back Bits, ETC) // Int Cmddoit (ClientData ClientData, TCL_INTERP * PINTERP, INT Argc, Char * Argv []) {Int Islot, Ivalue, ITRUNK, ICHAN; Char Stext [64]; fprintf (stderr, "* ***** DOING IT / N "); for (Itrunk = first_trunk; itrunk <= last_trunk; iTrunk ) {sprintf (Stext," Entrytrunk (% D) ", iTrunk); iValue = ATOI (Tcl_Getvar (Pinterp, Stext , 0); ifmem_p-> serv_shelf [iTrunk] = iValue; fprintf (stderr, "Card (2) (% D) =% D / N", ITRUNK, IVALUE); Sprintf (Stext, "EntrytrunkCard (% d) ", iTrunk); islot = ATOI (Tcl_Getvar (Pinterp, Stext, 0)); Sprintf (Stext," Entrytrunkchan (% D) ", ITRUNK); ICHAN = ATOI (TCL_GETVAR (Pinterp, Stext, 0)); IF Islot == 0 || islot> 30) Continue; if (iChan == 0 | iChan> 30) Continue; ifmem_p-> timeesw_in_ctrl [2] [iChan] = iTrunk; fprintf (stderr, "TM2_IN (% D) =% D / N ", ICHAN, ITRUNK); ifmem_p-> timeesw_out_ctrl [2] [islot] = ichan; fprintf (stderr," TM2_OUT (% D) =% D / N ", ISLOT, ICHAN); ICHAN); ifmem_p -> spacesw_ctrl [ichan] = 10; fprintf (stderr, "ss (% d) = 10 / n", ICHAN);} // end for - loop through mfsendersfprintf (stderr, "/ n / n"); for (islot = first_mfsend; islot <= last_mfsend; islot ) {sprintf (Stext, "Entrymfs (% d)", ISLOT); IVALUE = ATOI (TCL_GETVAR (Pinterp, Stext, 0)); ifmem_p-> serv_shelf [islot] = iValue; fprintf (stderr, "card (2) (% d) =% d / n", islot, ivalue; sprintf (stext, "
Entrymfstrunk (% d) ", ISLOT); ITRUNK = ATOI (Tcl_Getvar (Pinterp, Stext, 0)); Sprintf (Stext," Entrymfschan (% D) ", ISLOT); ICHAN = ATOI (TCL_Getvar (Pinterp, Stext, 0 ); if (iTrunk
Original author:
Source URL
Chinese translator: Lu Shaofei