An Introduction To Embedded Tk (page 9 of 32)

[Previous Page][Next Page][Table of Contents]

6.2 The ET_PROC Statement

The core of the decimal clock program is a new Tcl/Tk command, DecimalTime, that returns the current time of day as a decimal number of hours. This new command is written in C, using the special ET_PROC construct of ET. The code looks like this:

  #include "tcl.h"
  #include <time.h>

  ET_PROC( DecimalTime ){
    struct tm *pTime;  /* The time of day decoded */
    time_t now;        /* Number of seconds since the epoch */

    now = time(0);
    pTime = localtime(&now);
    sprintf(interp->result,"%2d.%03d",pTime->tm_hour,
      (pTime->tm_sec + 60*pTime->tm_min)*10/36);
    return ET_OK;
  }
The magic is in the ET_PROC keyword. The et2c preprocessor recognizes this keyword and converts the code that follows it into a compilable C function that implements the Tcl/Tk command. In general, you can create new Tcl/Tk commands using a template like this:
  ET_PROC( name-of-the-new-command ){
    /* C code to implement the command */
  }
You could, of course, construct approprate C functions by hand, but that involves writing a bunch of messy details that detract from the legibility of the code. The ET_PROC mechanism is much easier to write and understand, and much less subject to error.

Though they do not appear explicitly in the source code, every function created using ET_PROC has four formal parameters.

The decimal clock example uses the interp formal parameter on the sixth line of the ET_PROC function. In particular, the DecimalTime function writes its result (e.g. the time as a decimal number) into the result field of interp. It's OK to write up to about 200 bytes of text into the result field of the interp parameter, and that text will become the return value of the Tcl/Tk command. If you need to return more than about 200 bytes of text, then you should set the result using one of the routines from the Tcl library designed for that purpose: Tcl_SetResult(), Tcl_AppendResult(), or Tcl_AppendElement(). (These routines are documented by Tcl's manual pages under the name ``SetResult''.) If all this seems too complicated, then you can choose to do nothing at all, in which case the return value defaults to an empty string.

Another important feature of every ET_PROC function is its return value. Every ET_PROC should return either ET_OK or ET_ERROR, depending on whether or not the function encountered any errors. (ET_OK and ET_ERROR are #define constants inserted by et2c and have the save values as TCL_OK and TCL_ERROR.) It is impossible for the DecimalClock function to fail, so it always returns ET_OK, but most ET_PROC functions can return either result.

Part of Tcl's result protocol is that if a command returns ET_ERROR it should put an error message in the interp->result field. If we had wanted to be pedantic, we could have put a test in the DecimalTime function to make sure it is called with no arguments. Like this:

  ET_PROC( DecimalTime ){
    struct tm *pTime;  /* The time of day decoded */
    time_t now;        /* Number of seconds since the epoch */

    if( argc!=1 ){
      Tcl_AppendResult(interp,"The ",argv[0],
        " command should have no argument!",0);
      return ET_ERROR;
    } 
    /* The rest of the code is omitted ... */
  }
New Tcl/Tk commands that take a fixed format normally need to have some checks like this, to make sure they aren't called with too many or too few arguments.

[Next Page][Table of Contents]