510 likes | 668 Views
Programming Using Tcl/Tk Week 5. Seree Chinodom seree@buu.ac.th http://lecture.compsci.buu.ac.th/TclTk. First Things First. Homework #2 Some good work Project: Hand them in, if you've got 'em To have your project returned, send SASE to: Ernest Friedman-Hill 1206 Caribou Place
E N D
Programming Using Tcl/TkWeek 5 Seree Chinodom seree@buu.ac.th http://lecture.compsci.buu.ac.th/TclTk
First Things First • Homework #2 • Some good work • Project: Hand them in, if you've got 'em • To have your project returned, send SASE to: Ernest Friedman-Hill 1206 Caribou Place Davis, CA 95616 • Grading method choice • CLG: Credit, letter grade • CP/NP: Credit / No Credit (Pass / Fail) • NC: Not for credit
What We'll Do Today • Extending Tcl with C • A look at some third-party Tcl extensions I use • Expect • BLT • TclDii • The future of Tcl/Tk
Extending Tcl: Outline • Philosophy: focus on primitives. • Basics: interpreters, executing scripts. • Implementing new commands. • Managing packages; dynamic loading. • Managing the result string. • Useful library procedures: parsing, variables, lists, hash tables.
Philosophy • Usually better to write Tcl scripts than C code: • Faster development (higher level, no compilation). • More flexible. • Why write C? • Need access to low-level facilities (hardware). • Efficiency concerns (iterative calculations). • Need more structure (code is complex). • Implement new Tcl commands that provide a few simple orthogonal primitives: • Low-level to provide independent access to all key features. • High-level to hide unimportant details, allow efficient implementation.
Example: Weather Reports • Goal: retrieve weather reports over network from servers. • Tcl command set #1: • Retrieve report, format, print onstandard output. • Tcl command set #2: • Open socket to weather server. • Select station. • Retrieve first line of report.... • Tcl command set #3: • Return list of available stations. • Given station name, retrieve report. Too high-level (inflexible) Too low-level (tedious) Just right
Designing New Commands • Choose textual names for objects: .dlg.bottom.ok file3 or stdin • Use hash tables to map to C structures. • Object-oriented commands: .dlg.bottom.ok configure -fg red • Good for small numbers of well-defined objects. • Doesn't pollute name space. • Allows similar commands for different objects. • Action-oriented commands: string compare $x $y • Good if many objects or short-lived objects.
Designing New Commands, cont'd • Formatting command results: • Make them easy to parse with Tcl scripts:tmp 53 hi 68 lo 37 precip .02 sky part • Make them symbolic wherever possible, e.g. not53 68 37 .02 7 • Use package prefixes in command names and global variables: wthr_stationswthr_reportmidi_play • Allows packages to coexist without name clashes.
Interpreters • Tcl_Interp structure encapsulates execution state: • Variables. • Commands implemented in C. • Tcl procedures. • Execution stack. • Can have many interpreters in a single application (but usually just one). • Creating and deleting interpreters: Tcl_Interp *interp; interp = Tcl_CreateInterp(); Tcl_DeleteInterp(interp);
Executing Tcl Scripts int code; code = Tcl_Eval(interp, "set a 1"); code = Tcl_EvalFile(interp, "init.tcl"); code = Tcl_VarEval(interp, "set ", a, " 1"); • code indicates success or failure: • TCL_OK: normal completion. • TCL_ERROR: error occurred. • interp->resultpoints to string: result or error message. • Application should display result or message for user.
Where Do Scripts Come From? • Read from standard input (see tclMain.c). • Read from script file (see tclMain.c). • Associate with X events, wait for events, invoke associated scripts (see tkMain.c). • Embeddded in C code (fixed or private scripts)
Creating New Tcl Commands • Write command procedure in C: int EqCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { if (argc != 3) { interp->result = "wrong # args"; return TCL_ERROR; } if (!strcmp(argv[1], argv[2])) interp->result = "1"; else interp->result = "0"; return TCL_OK;}
Creating New Tcl Commands, cont'd • Register with interpreter: Tcl_CreateCommand(interp, "eq", EqCmd, (ClientData) NULL, ...); • Once registered, EqCmd will be called whenever eq command is invoked in interp. • Command can be deleted later Tcl_DeleteCommand(interp, "eq"); • This is most useful for 'object' commands
ClientData Tcl_CreateCommand(interp, "eq", EqCmd,clientData, ...);int EqCmd(ClientData clientData, ...) {...} • Used to pass any one-word value to command procedures and other callbacks. • clientData is usually a pointer to data structure manipulated by procedure. • Cast pointers in and out of ClientData type: • Tcl_CreateCommand(... (ClientData) gizmoPtr, ...); • gizmoPtr = (Gizmo *) clientData; • Lets many object commands share one command proc
Conventions For Packages Goal: make it easy to develop and use Tcl extensions. 1. Use package prefixes to prevent name conflicts: • Pick short prefix for package, e.g. rdb. • Use in all global names: • C procedure: Rdb_Open • C variable: rdb_NumRecords • Tcl command: rdb_query • See Tcl book and Tcl/Tk Engineering Manual for more details.
Packages, cont'd 2. Create package initialization procedure: • Named after package: Rdb_Init. • Creates package's commands. • Evaluates startup script, if any. int Rdb_Init(Tcl_Interp *interp) { Tcl_CreateCommand(...); Tcl_CreateCommand(...); ... return Tcl_EvalFile(interp, "/usr/local/lib/rdb/init.tcl");}
Packages, cont'd 3. To use package: • Compile as shared library, e.g. on Solaris:cc -K pic -c rdb.cld -G -z text rdb.o -o rdb.so • Dynamically load into tclsh or wish:load rdb.so Rdb • Tcl will call Rdb_Init to initialize the package. • Note: this is new since the text was published; much nicer than old static mechanism! -Kpic: position independent code. -G: produce a shared object. undefined symbols allowed. -z text: force library to be read-only
The load command • Several forms load filename load filename packageName load "" packageName where filename is libXYZ.so packageName is XYZ • You can use info sharedlibextension to decide between .dll, .so, etc. • You can use info loaded to see what packages have been loaded
Packages, cont'd • You can also load packages statically: Tcl_StaticPackage(Tcl_Interp interp, char * pkgName, Tcl_PkgInitProc *InitProc, Tcl_PkgInitProc *safeInitProc) … then load "" XYZ • Dynamic loading is to be preferred
Managing The Result String • Need conventions for interp->result: • Permit results of any length. • Avoid malloc overheads if possible. • Avoid storage reclamation problems (leaks). • Keep as simple as possible. • Normal state of interpreter (e.g., whenever command procedure is invoked): • Default: command returns empty string. interp result freeProc ""
Result String, cont'd • Option 1: (semi-) static result. interp->result = "0"; • Option 2: use pre-allocated space in interp. sprintf(interp->result, "Value is %d", i); interp result "0" freeProc "" interp result freeProc ~200 bytes "Value is 2"
Result String, cont'd • Option 3: allocate new space for result. interp->result = malloc(2000);...interp->freeProc = free; • Tcl will call freeProc (if not NULL) to dispose of result. • Mechanism supports storage allocators other than malloc/free (if they have the same signatures!) interp result freeProc free ""
Procedures For Managing Result • Option 4: use library procedures. Tcl_SetResult(interp, string, ...); replaces old value Tcl_AppendResult(interp, string, string, ... string, (char *) NULL); extends old value Tcl_AppendElement(interp, string); extends old value, as a list Tcl_ResetResult(interp); clears old value
Utility Procedures: Parsing • Used by command procedures to parse arguments: int value, code;code = Tcl_GetInt(interp, argv[1], &value); • Stores integer in value. • Returns TCL_OK or TCL_ERROR. • If parse error, returns TCL_ERROR and leaves message in interp->result.
Parsing (cont'd) • Other procedures: Tcl_GetDouble Tcl_ExprDouble Tcl_GetBoolean Tcl_ExprBoolean Tcl_ExprLong Tcl_ExprString • Tcl_GetBoolean accepts 'yes', 'false', 1, 0… • Expr- variations interpret argument as an expression
Utility Procedures: Variables • Read, write, and unset: char *value;value = Tcl_GetVar(interp, "a", ...);Tcl_SetVar(interp, "a", "new", ...);Tcl_UnsetVar(interp, "a", ...); • Set traces: Tcl_TraceVar(interp, "a", TCL_TRACE_READS|TCL_TRACE_WRITES, traceProc, clientData); • traceProc will be called during each read or write of a: • Can monitor accesses. • Can override value read or written.
Other Utility Procedures • Parsing, assembling proper lists: Tcl_SplitList(...)Tcl_Merge(...) • Flexible hash tables: Tcl_InitHashTable(...)Tcl_CreateHashEntry(...)Tcl_FindHashEntry(...)Tcl_DeleteHashEntry(...)Tcl_DeleteHashTable(...) • Like having Tcl associative arrays in C • Excellent way to store clientData records for 'object-oriented' command model
Other Utilities (cont'd) • Dynamic strings: Tcl_DStringInit(...) Tcl_DStringAppend(...) Tcl_DStringAppendElement(...) Tcl_DStringValue(...) Tcl_DStringFree(...) • Dynamic strings grow efficiently without bounds • Like a good String class in C++ • Used internally by Tcl for result management, etc
Extending Tcl Summary • Interfaces to C are simple: Tcl was designed to make this true. • Focus on primitives, use Tcl scripts to compose fancy features.
Widgets Tk Xlib Writing a Widget for Tk • Good News: One widget can work on UNIX, Win32, Mac • Tk port uses port of Xlib to support graphics • Bad News: You still have to write to Xlib! Tk only uses Xlib, the lowest-level part of the X libraries. It doesn't use Xt, Athena, Motif, etc. To draw, you have to use Xlib, too.
Writing a Widget for Tk • Tk supplies utilities • 3D outline drawing • Font utilities • Event notification, timers, idle procs • You supply • Tcl commands • Initialization procedure • Configuration table • Event handlers • Deletion callbacks • Use object-oriented command paradigm • One Tcl command per widget class • One Tcl command per widget instance
Expect • Terrific for creating GUIs for interactive command-line apps • Terrific for reacting to prompts from command-line apps • Expect can • Automate tedious interactive processes • Glue GUI actions to simulated keyboard outputs • Reattach subprocess to keyboard • Works only on true POSIX (UNIX) systems • Uses pseudottys (ptys), a UNIX construct
Expect (cont'd) • Commands: spawn: like background exec, but opens two-way pipe spawn telnet herzberg 80 expect: responds to patterns from pipe expect { "connection refused" exit "unknown host" complain DNS login: login_proc default interact } interact:reconnect two-way pipe to console
BLT • Several 'megawidgets' • blt_graph is most useful • Other commands: blt_htext blt_drag&drop blt_barchart blt_table
BLT Graph Widget blt_graph .g -height 175 -width 200 -font \ "-*-times-medium-r-normal-*-*-80-*-*-*-*-*-*" .g legend configure -font \ "-*-times-medium-r-normal-*-*-80-*-*-*-*-*-*" \ -anchor nw -position "@65,10" -relief ridge .g yaxis configure -title "" .g xaxis configure -title "Time (sec)" .g element create "Series1" -xdata $x1 -ydata $y1 \ -linewidth 1 -fg red -bg blue -label "Velocity" .g element create "Series2" -xdata $x2 -ydata $y2 \ -linewidth 1 -fg green -bg blue -label "Stroke"
TclDii • Lets Tcl/Tk talks to CORBA objects • CORBA lets objects written in different languages communicate • Tk GUIs for remote objects are easy and powerful • TclDii test scripts faster and easier than C++ code
A Look Ahead Tcl 7.5p1 Tk 4.1p1 Tcl 7.6 Tk 4.2 Grid manager revisions for use by SpecTcl. Tcl 7.5 Tk 4.1 Tcl 7.6plug Tk 4.2plug Embedding, other features for Netscape plugin. Tcl 7.7 Tk 4.3 Native look and feel for PC and Mac. Tcl 8.0 Tk ?.? Bytecode compiler.
Tcl 7.6 and Tk 4.2 • Major revision of gridder, needed for SpecTcl FCS. • C API change for channel drivers (eliminate Tcl_File usage). • No other changes except bug fixes. • Now in Beta, final release any day now.
Tcl 7.6plug and Tk 4.2plug • Features needed for Netscape plugin: • Application embedding: frame .x.y -container 1 toplevel .t -use [winfo id .x.y] wish -use 0x6800004 • Focus revision. • Safe-Tk, security models. • Already released in plugin binaries. • No source release until Tcl 7.7/Tk4.3.
Tcl 7.7 and Tk 4.3 • Native widgets on PC and Mac. • New menu mechanism: • Menu bars implemented with menu widgets. • New -menu option for toplevel windows. • Tear-off menus are clones (consistency guaranteed). • Can use same menu in several places. • Hide tear-off entries? • New font mechanism: (nice for non-UNIX!) label .l -font {times 12 bold} font create title -family Helvetica \ -size 24 -weight bold label .l2 -font title font configure title -size 36
Tcl 7.7 and Tk 4.3, cont'd • Virtual bindings, event generation: event add <<Paste>> <Control-v> bind Entry <<Paste>> {...} event generate .t ButtonPress \ -button 1 -x 47 -y 18 • Standard dialogs. • Portable file commands: rm, mv, mkdir, rmdir, ... • Binary I/O support: • Read/write blocks of data. • Insert/extract fields of blocks. • Copy between channels.
Tcl 7.7 and Tk 4.3, cont'd • Other possible additions: • Megawidgets. • Image revisions: • No dithering. • Better memory usage. • Channel support. • ... • More text improvements (smooth scrolling, etc.). • Schedule estimate: • First alpha release October-November 1996. • Final release Q2 1997.
Tcl 8.0 • Byte-code compiler (see ftp.neosoft.com for 3rd-party attempts) • New object system for data representation. • New C APIs for command procedures, many other Tcl library procedures (old interfaces still supported, but slow). • Namespaces?
Tcl 8.0, cont'd • Possible changes in semantics: • More aggressive list syntax checking, conversion: lappend, lindex. • Changes to error messages, errorInfo (line numbers?). • Schedule estimate: • First alpha release October 1996. • Final release Q2 1997? • Additional speedups in later releases.
Other Projects • SpecTcl and SpecJava. • WebEdit, microscripting: • Edit Web pages WYSIWYG with WebEdit. • Insert Tcl/Tk scripts at various places. • Scripts fire at interesting times: • Site configuration time. • Page fetch (CGI). • On client machine (via plugin). • Safe-Tcl: • Better Tk support, socket communication. • Develop interesting security policies. • Add authentication, MD5 (signatures).