Provided by: tclx8.4-doc_8.4.0-3.1_all bug

NAME

       TclCommandWriting - Writing C language extensions to Tcl.

OVERVIEW

       This  document  is intended to help the programmer who wishes to extend Tcl with C language routines.  It
       should also be useful to someone wishing to add Tcl to an existing editor, communications program, window
       manager, etc.  Experienced extension writers may find this manual helpful in rewriting their applications
       to use the new Tcl object system.  We assume you are already fluent in the  C  programming  language  and
       that you have built and installed Tcl on your machine.

       Information  on the available C interface routines to Tcl can be found in the *.3 manual pages in the doc
       directory of the baseline Tcl distribution, and in the *.3 manpages in the doc directory of Extended Tcl.

TCL OBJECT SYSTEM

       With the release of Tcl version 8, Tcl has a new system for managing Tcl values internally.  To  the  Tcl
       programmer,  the new objects look and act like strings, as before.  But at the C level, these objects can
       now also hold cached internal representations of the strings in various native datatypes.   For  example,
       an  object  containing  a  string  consisting  of  an  integer,  will now maintain a machine-code integer
       representation, if an integer representation has been needed.  Using these objects is much more efficient
       than using the older-style Tcl strings, although the older style is still (currently) supported.

       Although the object system has almost no effect at all on how the Tcl programmer  uses  Tcl,  the  object
       system's  C  interfaces to strings, integers, lists, etc., have changed considerably.  While converting a
       package to use the new system can be a lot of work, the combination of the object system, which saves Tcl
       from having to constantly convert strings to  integers  and  back,  etc.,  and  the  on-the-fly  bytecode
       compiler  (which  keeps  Tcl from having to continually reparse code it is to execute) yield Tcl programs
       that routinely execute several times more quickly than with previous versions (Tcl 7 and before), and  in
       some cases run as much as 2500 (!) times faster than before.

       We  have chosen, then, to rewrite the Command Writer's manpage, which has been shipping with Extended Tcl
       for a number of years, to produce this new version based on the new  object  system.   The  old  manpage,
       based  on  the  older string-oriented routines, will still be included in TclX releases for now, as it is
       still relevant to Tcl releases through version 7, and may be of use to those modifying/upgrading packages
       written for the old model.  The old manual will be dropped from the release once we deem it unneeded; the
       old interfaces should now be considered legacy interfaces, and all new development should be  done  using
       the new object interfaces, unless backwards compatibility to pre-Tcl-8 releases is needed.

A SIMPLE C EXTENSION

       All  C-based  Tcl commands are called with four arguments: a client data pointer, an interpreter pointer,
       an argument count and a pointer to an array of Tcl objects containing the arguments to the command.

       A simple C extension to Tcl is now presented, and described below:

           #include "tcl.h"

           int App_DumpArgsObjCmd(clientData, interp, objc, objv)
               void          *clientData;
               Tcl_Interp    *interp;
               int            objc;
               Tcl_Obj      **objv;
           {
                   int   i;
                int   stringLen;
                char *stringPtr;

                   for (i = 1; i < objc; i++) {
                     stringPtr = Tcl_GetStringFromObj (objv [i], &stringLen);
                           printf("%s", stringPtr);
                     if (i < objc - 1) printf(" ");
                   }
                   printf("\n");
                   return TCL_OK;
           }

       The client data pointer will be described later.

INTERPRETERS

       The interpreter pointer is the ``key'' to an interpreter.  It is returned by Tcl_CreateInterp and is used
       extensively within Tcl, and will be used by your C extensions.  The data  structure  pointed  to  by  the
       interpreter  pointer,  and  all  of  the  subordinate  structures  that  branch  off of it, make up a Tcl
       interpreter, which includes all of the currently defined procedures, commands, variables, arrays and  the
       execution state of that interpreter.  (For more information on creating and deleting interpreters, please
       examine  the CrtInterp(3) manpage in the core Tcl distribution.  For information on creating interpreters
       that include the commands provided by Extended Tcl, check out the TclX_Init(3) manpage of  Extended  Tcl.
       For  a  manual  page describing the user-visible fields of a Tcl interpreter, please look at Interp(3) in
       core Tcl.)

OBJECT COUNT AND ARGUMENTS

       The argument count, or object count (objc), and pointer to an array of pointers to  Tcl  objects  of  the
       command's  arguments  (objv)  is  handled by your C code, in a manner similar to the one you would use in
       writing a C main function -- an argument count and array of pointers works the same as in a C main  call;
       pointers  to  the  arguments  to  the function are contained in the objv array.  Similar to a C main, the
       first argument (objv[0]) is an object containing the name the routine was called as (in  a  C  main,  the
       name the program was invoked as).

       In  Tcl,  however, the array of pointers are not pointers to character strings (although they were in all
       version of Tcl before 8.0).

       In the above example, all of the arguments are output with a space between each one  by  looping  through
       elements of the objv array from one to the argument count, objc, and a newline is output to terminate the
       line  --  a  simple  ``echo'' command.  This example uses printf for simplicity.  Of course in production
       code you would want to  use  the  Tcl  filesystem  interfaces.   See  GetFile(3)  and  friends  for  more
       information.

       All arguments from a Tcl call to a Tcl C extension are passed as Tcl Objects.  If your C routine wants to
       look  at  one  of  those  arguments  as  an  integer,  you  need to make a call to a routine to fetch the
       representation of the object that you need.  In the earlier example, for  instance,  Tcl_GetStringFromObj
       is  called  to  obtain a textual representation of an object.  Additional routines are available to fetch
       the representation of a data element as other data types.   Tcl_GetBooleanFromObj,  Tcl_GetDoubleFromObj,
       Tcl_GetIntFromObj,  Tcl_GetLongFromObj,   and  Tcl_GetIndexFromObj,  fetch  object representations of Tcl
       strings as booleans, double-precision floating point, integer, long integer, and lists, among others.

       These routines automatically leave an appropriate error message in the Tcl  interpreter's  result  object
       and return TCL_ERROR if a conversion error occurs.   (For more information on these routines, please look
       at the Object(3) manpage in the core Tcl distribution.)

RETURNING RESULTS

       As  you  might  expect, the API for setting results from C extensions has changed significantly under the
       object system.  The old technique of writing small results directory into the interpreter's result buffer
       is no longer used, for example.  The notion of having to tell Tcl whether a result is static  or  dynamic
       is  also a thing of the past.  Under the object system, results are objects that are set up by your code,
       and objects are freed when their reference counts say they should be.  More on this later.

       If you program produces a numeric result, it should set the result object to contain that numeric  value.
       A common way of doing this is something like...

               Tcl_Obj *obj;

               obj = Tcl_GetObjResult (interp);
            Tcl_SetIntObj (obj, value);

       The  above  code  obtains  a  pointer to the result object (an object made available to your routine that
       you're supposed to store your results into) and sets the integer value value into it.

       Another way to do it would be to set up a new object and tell Tcl that this object contains the result...

               Tcl_Obj *resultObj;

               /* create a new object for use as a result */
            resultObj = Tcl_NewObj ();

            Tcl_SetIntObj (obj, value);
            Tcl_SetObjResult (interp, resultObj);

       Understanding how results are passed back to Tcl is essential to the C extension  writer.   Please  study
       the SetObjResult(3) manual page in the Tcl distribution for more information.

VALIDATING ARGUMENTS

       It  is  a design goal of Tcl that no Tcl program be able to cause Tcl to dump core.  It is important that
       the extension writers, likewise, use the avaiable methods and tools to make sure that their extensions do
       not allow unchecked input, for example, to cause the code to get some kind of runtime exception.

       The object system has simplified, to some degree, the task of validating arguments, in  that  the  object
       system automatically attempts type conversions as needed, and will return an error when a type conversion
       fails.

       A simple, but important, check that every C extension should do is verify that it has the right number of
       arguments.

       The  act  of  trying  to use, say, a string as an integer, implicitly performs the type conversion of the
       string and, if it doesn't work as an integer, returns TCL_ERROR.  The  developer  should  check  for  the
       TCL_ERROR  return  from  all of the GetXxxFromObj commands, and handle them as appropriate.  Usually this
       will mean propagating the error on back to the user, or to an intevening catch, as the case may be.

       You should also check that values are in range (when their ranges are known), and so forth.  When C  data
       structures  need  to  be handled in Tcl in some form or another, yet the contents of the data must remain
       opaque to Tcl, as is usually the case with binary data (although futures releases of Tcl are expected  to
       have native abilities to read, write and manipulate binary data instrinsically), handles need to be used.
       Handles will be described and examples presented, later in this doc.

ANOTHER C EXTENSION - THE MAX COMMAND

       In the command below, two or more arguments are compared, and the one with the maximum value is returned,
       if  all  goes  well.   It  is  an error if there are fewer than two arguments (the pointer to the ``max''
       command text itself, objv[0], and a pointer to at least one object to compare the values of).

           int
           Tcl_MaxCmd (clientData, interp, objc, objv)
               char         *clientData;
               Tcl_Interp   *interp;
               int           objc;
               Tcl_Obj     **objv;
           {
               int maxVal = MININT;
               int value, idx;

               if (objc < 3)
                return TclX_WrongArgs (interp, objv[0],
                                          " num1 num2 [..numN]");

               for (idx = 1; idx < objc; idx++) {
                   if (Tcl_GetIntFromObj (interp, objv[idx], &value) != TCL_OK)
                       return TCL_ERROR;

                   if (value > maxVal) {
                       maxVal = value;
                   }
               }
            Tcl_SetIntObj (Tcl_GetObjResult (interp), value);
               return TCL_OK;
           }

       Here we introduce the Extended Tcl helper function TclX_WrongArgs.  This routine makes it easy to  create
       an error message and error return in response to the common mistake of being called with a wrong number.

       Tcl_GetIntFromObj  is  used  to  fetch  the integer values of the remaining arguments.  If any fail to be
       converted, we return a Tcl error.  If an interpreter is specified in the call  to  Tcl_GetIntFromObj,  an
       appropriate error message about the conversion failure will be left in the result, so we do that here.

       After  examining all of the arguments to find the largest value, we set the result object to contain that
       value, and return TCL_OK.

RETURNING RESULTS

       When Tcl-callable functions complete, they  should  normally  return  TCL_OK  or  TCL_ERROR.   TCL_OK  is
       returned  when  the  command  succeeded,  and  TCL_ERROR  is returned when the command has failed in some
       abnormal way.  TCL_ERROR should be returned for all syntax errors, non-numeric values when  numeric  ones
       were  expected,  and  so  forth.   Less  clear  in some cases is whether Tcl errors should be returned or
       whether a function should just return a status value.  For example, end-of-file during a gets  returns  a
       status,  but  open  returns an error if it fails.  Errors can be caught from Tcl programs using the catch
       command.  (See Tcl's catch(n) and error(n) manual pages.)

       Less common return values are TCL_RETURN, TCL_BREAK and TCL_CONTINUE.  These are used if you  are  adding
       new  control and/or looping structures to Tcl.  To see these values in action, examine the source code to
       Extended Tcl's loop commands.  Tcl's while, for and if commands used to work in the just same manner, but
       are now compiled into bytecode by the bytecode for performance.

ANOTHER C EXTENSION - THE LREVERSE COMMAND

       In the command below, a list is passed as an argument, and a list containing all of the elements  of  the
       list  in  reverse order is returned.  It is an error if anything other than two arguments are passed (the
       pointer to the ``lreverse'' command text itself, objv[0], and a pointer to the list to reverse.

       Once lreverse has determined that it has received the correct number of arguments, Tcl_ListObjGetElements
       is called to split the list into its own objc count of elements and objv array of pointers to the  list's
       elements.

       lreverse  then  operates on the array of pointers, swapping them from lowest to highest, second-lowest to
       second-highest, and so forth.

       Tcl_ListObjAppendElement is called on successive list elements to build up the new list, which is finally
       returned as result of the command.

       int
       Tcl_LreverseObjCmd(notUsed, interp, objc, objv)
           ClientData    notUsed;        /* Not used. */
           Tcl_Interp   *interp;         /* Current interpreter. */
           int           objc;           /* Number of arguments. */
           Tcl_Obj     **obj;            /* Argument strings. */
       {
           int listObjc, lowListIndex, hiListIndex;
           Tcl_Obj **listObjv;
           char *temp, *resultList;
           Tcl_Obj **newListObjv;

           /* Verify argument count.  Since we take only one argument, argument
            * count must be 2 (command plus one argument).
            */
           if (objc != 2)
            return TclX_WrongArgs (interp, objv [0], "list");

           /* Create an object to handle the new list we're creating */
           newListObjv = Tcl_NewObj();

           /* Crack the list at objv[1] into its own count and array of object
            * pointers.
            */
           if (Tcl_ListObjGetElements (interp, objv[1], &listObjc, &listObjv) != TCL_OK) {
            return TCL_ERROR;
           }

           /* For each element in the source list from last to first, append an
            * element to the new list.
            */
           for (listIndex = listObjc - 1; listIndex >= 0; listIndex--) {
            Tcl_ListObjAppendElement (interp, newListObjv, listObjv[listIndex]);
           }
       FIX: NEED TO RETURN THE LIST.
           return TCL_OK;
       }

INSTALLING YOUR COMMAND

       To install your command into Tcl you must call  Tcl_CreateObjCommand,  passing  it  the  pointer  to  the
       interpreter  you  want  to install the command into, the name of the command, a pointer to the C function
       that implements the command, a client data pointer, and a pointer to an optional callback routine.

       The client data pointer and the callback routine will be described later.

       For example, for the max function above  (which,  incidentally,  comes  from  TclX's  tclXmath.c  in  the
       TclX7.4/src directory):

           Tcl_CreateCommand (interp, "max", Tcl_MaxCmd, (ClientData)NULL,
                             (void (*)())NULL);

       In  the  above  example, the max function is added to the specified interpreter.  The client data pointer
       and callback function pointer are NULL.  (For complete information on Tcl_CreateCommand and its companion
       routine, Tcl_CommandInfo, please examine the CrtCommand(3) command page in the core Tcl distribution.)

DYNAMIC STRINGS

       Dynamic strings are an important abstraction that first became available with Tcl 7.0.  Dynamic  strings,
       or  DStrings,  provide a way to build up arbitrarily long strings through a repeated process of appending
       information to them.  DStrings reduce the amount of allocating and copying required to add information to
       a string.  Further, they simplify the process of doing so.

       At first glance, it may seem that the object system supersedes  DStrings.   It  does  not,  in  that  the
       performance  improvements  made  possible  by  the lazy conversion of an object's representation from one
       datatype to another does not come into play much while constructing strings as the string  representation
       is always available either without any type conversion or where type conversion would be necessary in any
       case  as  a  string  representation  of  the  object  is  required  when strings are being constructed by
       concatenation, etc.

       It should be noted, however, that the C  level  string  manipulation  capabilites  of  objects,  such  as
       Tcl_AppendToObj  and  Tcl_AppendStringsToObj,  are  often  plenty  enough  for  what you need to do.  For
       complete information on dynamic strings, please examine the  DString(3)  manual  page  in  the  core  Tcl
       distribution.   For  more  on  Tcl  object's  string-oriented  calls,  seek  Tcl_StringObj(3) in the same
       location.

CLIENT DATA

       The client data pointer provides a means for Tcl commands to have data associated with them that  is  not
       global  to  the  C program nor included in the Tcl core.  Client data is essential in a multi-interpreter
       environment (where a single program has created and is making use of multiple Tcl interpreters) for the C
       routines to maintain any permanent data they need on a per-interpreter basis.  If needed static data  was
       simply  declared  static  in  C,  you  will probably have reentrancy problems when you work with multiple
       interpreters.

       Tcl solves this through the client data mechanism.  When you are about to  call  Tcl_CreateObjCommand  to
       add  a  new  command  to  an  interpreter,  if  your  command  needs  to keep some read/write data across
       invocations, you should allocate the space, preferably using Tcl_Alloc instead of malloc, then  pass  the
       address of that space as the ClientData pointer to Tcl_CreateObjCommand.

       When  your  command is called from Tcl, the ClientData pointer you passed to Tcl_CreateObjCommand will be
       passed to your C routine through the ClientData pointer calling argument.

       Commands that need to share this data with one another can do so by using  the  same  ClientData  pointer
       when the commands are added.

       It is important to note that the Tcl extensions in the tclX8.0.0 directory have had all of their data set
       up  in  this  way.   Since  release  6.2,  Extended  Tcl  has  supported multiple interpreters within one
       invocation of Tcl.

THEORY OF HANDLES

       Sometimes you need to have a data element that isn't readily representable as a string  within  Tcl,  for
       example  a  pointer  to a complex C data structure.  It is not a good idea to try to pass pointers around
       within Tcl as strings by converting them to and from hex or integer representations, for example.  It  is
       too easy to mess one up, and the likely outcome of doing that is a core dump.

       Instead  we have developed and made use of the concept of handles.  Handles are identifiers a C extension
       can pass to, and accept from, Tcl to make the transition between what your C code knows something as  and
       what  name  Tcl knows it by to be as safe and painless as possible.  For example, the I/O system included
       in Tcl uses file handles.  When you open a file from Tcl, a handle is returned of the form filen where  n
       is  a  file  number.   When  you  pass the file handle back to puts, gets, seek, flush and so forth, they
       validate the file handle by checking the the file text is present, then converting the file number to  an
       integer  that  they  use  to  look  into  a data structure of pointers to Tcl open file structures, which
       contain a Unix file descriptor, flags indicating whether or not the file is currently open,  whether  the
       file is a file or a pipe and so forth.

       Handles  have  proven so useful that, since TclX release 6.1a, general support has been available to help
       create and manipulate them.  Many of these capabilities have migrated into baseline Tcl.  If you  have  a
       similar  need,  you  might  like to use the handle routines documented in Handles(3) in Extended Tcl.  We
       recommend that you use a unique-to-your-package textual handle coupled with a specific identifier and let
       the handle management routines validate it when it's passed back.  It is much easier to track down a  bug
       with an implicated handle named something like file4 or bitmap6 than just 6.

       Note  that  Tcl's  object  offers  another  way for complex data structures to exist in parallel with and
       underneath Tcl strings.  As of this writing (May 30, 1997) this is fairly new territory, but  things  are
       looking good for the prospects of using the Tcl object system in this manner, and for enhancements to the
       object system that allow even Tcl objects to have methods in a very straightforward and simple way.

USING COMMANDS TO DO THE SAME THING, AND MORE

       Another  handle-like  technique,  first popularized in the Tk toolkit, offers handle-like capabilities as
       well as some neat additional capabilities.  That is to create a  new  Tcl  command,  from  C,  that  uses
       ClientData to keep a "handle" on its complex underlying data structure.  Then by having that command look
       at  its  second  argument for what it is to do (its sub-functions), you get these nice methods, where you
       have several additional sub-commands that don't pollute the global namespace and only work  on  (and  are
       available  with)  the  objects  (new  commands)  they  are  relevant  to.  For example, in Tk, creating a
       checkbutton (checkbutton .b) creates a new Tcl command (.b), that has methods to  configure  the  button,
       select, deselect, toggle and flash it.

       A lot of people think this is really the way to go, and I am pretty much leaning that way myself.  If you
       use  the  incr  tcl  script-level  object  system  for Tcl, objects that you define in Tcl will be highly
       compatible in terms of their command interfaces and configuration management with objects you create in C
       using the the command-and-ClientData technique described here.  I believe Tk has some nice facilities for
       making this easy for the Tcl programmer.  Itcl certainly does.

TRACKING MEMORY CORRUPTION PROBLEMS

       Occasionally you may write code that scribbles past the end of an allocated piece of memory.   This  will
       usually  result  in  a  core  dump  or  memory  allocation  failure  sometime later in the program, often
       implicating code that is not actually responsible for the problem (as you start looking  from  the  point
       where the error is detected, which is usually where the later routine has failed).

       The  memory debugging routines included in Tcl can help find these problems.  Developed by Mark and Karl,
       the memory debugging routines are now part of baseline Tcl, and is to our knowledge the largest piece  of
       TclX  to  drop  into  the  core without being reengineered first.  (You see, summer back in '91, John was
       sitting in his office in the CS building at UC Berkeley trying to find a memory leak  somewhere  in  Tcl,
       when  he  was  paid  a  visit  by two long-haired-yet-polite programmers bearing gifts in the form of the
       technology grab-bag known as Extended Tcl.  He saw that, using  TclX's  malloc  routines,  Tcl  could  be
       prompted  to  print  the  filename  and line number of every single memory allocation that did not have a
       corresponding free.  It was just what the doctor ordered ;-) See Memory(TCL) for details.

INSTALLING YOUR EXTENSIONS INTO TCL

       To add your extensions to Tcl, you used to  have  to  statically  link  them,  together  with  any  other
       extensions,  into  a single binary executable image.  Today, although the statically linked executable is
       still an option, most operating systems, even Microsoft Windows, support shared libraries,  and  in  most
       cases,  Tcl can now make use of those shared libraries such that you extensions, and most others, can now
       be built a shared libraries that can be loaded in (using package require)  by  scripts  that  need  them.
       Shared libraries can simplify a Tcl installation, because only one copy of Tcl is required, rather than a
       hodepodge  of  combinations  of  applications that you might have found at a big Tcl site in the previous
       era.

GNU AUTOCONF

       While the build procedure for shared libraries varies from system to system, most Unix and Unix workalike
       systems will figure out the nuances of the compiler and linker arguments automatically when the configure
       script is run.  If you are building a package that you plan to  make  generally  available,  we  strongly
       recommend  that  you  use  GNU  autoconf (ftp://prep.ai.mit.edu/pub/gnu) to set up an automatic configure
       script for it.  Be forewarned that autoconf uses some pretty heavy duty shell and sed script magic to get
       the job done, and the learning curve can be pretty  steep.   Once  done  and  shaken  out,  though,  it's
       rewarding  to  know that your package can build and run on everything from a notebook to a Cray to a RISC
       SMP server.

       Application-specific startup is accomplished  by  creating  or  editing  the  Tcl_AppInit  function.   In
       Tcl_AppInit  you  should  add  a  call  to  an application-specific init function which you create.  This
       function should take the address of the interpreter it should install its commands into,  and  it  should
       install  those  commands  with  Tcl_CreateCommand  and  do any other application-specific startup that is
       necessary.

       The naming convention for application startup routines is  App_Init,  where  App  is  the  name  of  your
       application.   For  example,  to  add an application named cute one would create a Cute_Init routine that
       expected a Tcl_Interp pointer as an argument, and add the following code to Tcl_AppInit:

           if (Cute_Init (interp) == TCL_ERROR) {
            return TCL_ERROR;
           }

       As you can guess from the above example, if your init routine is unable  to  initialize,  it  should  use
       Tcl_AppendResult  to  provide  some  kind  of useful error message back to TclX, then return TCL_ERROR to
       indicate that an error occurred.  If the routine executed successfully, it should return TCL_OK.

       When you examine Tcl_AppInit, note that there is one call already there to install an application --  the
       call to TclX_Init installs Extended Tcl into the Tcl core.

MAKING APPLICATION INFORMATION VISIBLE FROM EXTENDED TCL

       TclX's  infox  command  can  return several pieces of information relevant to Extended Tcl, including the
       application's name, descriptive name, patch level and version.  Your application's startup can set  these
       variables to application-specific values.  If it doesn't, they are given default values for Extended Tcl.

       To  set  these  values, first be sure that you include either tclExtend.h or tclExtdInt.h from the source
       file that defines your init routine.  This will create external declarations for  the  variables.   Then,
       set the variables in your init route, for example:

           tclAppName = "cute";
           tclAppLongName = "Call Unix/Tcl Environment";
           tclAppVersion = "2.1";

       Note  that  the  default values are set by TclX_Init, so if you wish to override them, you must call your
       init routine in Tcl_AppInit after its call to TclX_Init.

EXTENDED TCL EXIT

       When Extended Tcl exits, Tcl_DeleteInterp may be called to free memory used by Tcl -- normally,  this  is
       only  called if TCL_MEM_DEBUG was defined, since Unix will return all of the allocated memory back to the
       system, anyway.  If TCL_MEM_DEBUG was defined, it is called so that any memory that was allocated without
       ever being freed can be detected.  This greatly reduces the amount of  work  to  detect  and  track  down
       memory  leaks, a situation where some piece of your code allocates memory repeatedly without ever freeing
       it, or at least without always freeing it.

       It is often necessary for an application to perform special cleanup functions upon  the  deletion  of  an
       interpreter  as  well.   To  facilitate  this  activity,  Tcl  provides the ability to perform a function
       callback when an interpreter is deleted.  To arrange for a C function to be called when  the  interpreter
       is deleted, call Tcl_CallWhenDeleted from your application initialization routine.  For details on how to
       use this function, read the CallDel(3) manual page that ships with core Tcl.

EXECUTING TCL CODE FROM YOUR C EXTENSION

       Suppose  you  are  in  the  middle  of  coding a C extension and you realize that you need some operation
       performed, one that would be simple from Tcl, but  possibly  excruciating  to  do  directly  in  C.   Tcl
       provides  a  number  of C-level interfaces whereby you can cause Tcl code to be executeed.  The old-style
       calls are Tcl_Eval, Tcl_VarEval, Tcl_EvalFile and Tcl_GlobalEval.  The results of these calls can be  dug
       out  of  the interpreter using Tcl_GetStringResult, if you want a string representation of the result, or
       Tcl_GetObjResult if you want the object.  (The use of interp->result to access the result string has been
       deprecated.)

       The Tcl object system adds Tcl_EvalObj and  Tcl_GlobalEvalObj.   The  difference  here  is  that  we  are
       evaluating  an  object,  not  just a string, and using these routines in preference to the aforementioned
       ones can result in a major performance improvement in your code, when the  code  is  executed  repeatedly
       (even if it only executes once but loops several times within itself), as these routines make it possible
       for  the  bytecode  compiler to compile the code being evaluated and save the compiled code with the data
       structure, in an implementation-dependent manner.

       For more information please consult the EvalObj(3) and Eval(3) manual pages within the Tcl distribution.

ACCESSING TCL VARIABLES AND ARRAYS FROM YOUR C EXTENSIONS

       In addition to the non-object-system ways of reading from and storing to Tcl  variables,  using  routines
       such  as  Tcl_SetVar2  and  Tcl_GetVar2,  Tcl  variables and arrays can be read from a C extension as Tcl
       objects by using the Tcl_ObjGetVar2 function, and  set  from  C  extensions  through  the  Tcl_ObjSetVar2
       function.

       Please  note  that  the  object versions do not carry forward analogues to the one-variable-name-argument
       Tcl_GetVar, Tcl_SetVar, and Tcl_UnsetVar.  If you know you have a scalar, call the  object  variable  get
       and  set  functions  with a NULL second argument.  If your variable name might contain an array reference
       via a self-contained embedded array index (i.e., I'm asking Tcl_ObjGetVar2 for "foo(5)" instead of  "foo"
       "5"), add the TCL_PARSE_PART1 to the flags in your call.

       While the fact that Tcl_ObjGetVar2 retrieves Tcl objects, rather than strings, is critical for the object
       system  to  be  able  to  provide  the performance boosts from "lazy" type conversion and the binary data
       capabilities, the arguments containing the variable name, or the array name and element name  if  they've
       been  split  out,  also  must  be  specified as Tcl objects rather than strings.  While this is useful on
       occasion, those writing C extensions for Tcl  in  the  post-object-system  era  usually  have  the  names
       available  as  plain  old char * variables, requiring conversion of the strings to objects before use and
       account for their possible destruction afterwards.

       To simplify the task in those cases, TclX adds the  TclX_ObjGetVar2S  subroutine.   It  works  just  like
       Tcl_ObjGetVar2,  except  the one or two variable name arguments are specified as strings, and the routine
       takes care of making and disposing of object equivalents.

       Tcl variables can be unset from C via the Tcl_UnsetVar and Tcl_UnsetVar2 functions.  There are  currently
       (as of 8.0) no object-system equivalents, so in the rare case where you have the name of the variable you
       want  unset  as  an  object  instead  of a string, you can call Tcl_GetStringFromObj to obtain the string
       representation first.

       For complete information on these functions, please refer to the ObjSetVar(3) and SetVar(3) manual  pages
       in the doc directory of the core Tcl distribution.

LINKING TCL VARIABLES TO C VARIABLES

       Tcl_LinkVar  and  Tcl_UnlinkVar  can  be  used  to  automatically  keep  Tcl  variables synchronized with
       corresponding C variables.  Once a Tcl variable has been linked to a C variable with Tcl_LinkVar, anytime
       the Tcl variable is read, the value of the C variable is converted (if necessary) and returned, and  when
       the Tcl variable is written, the C variable will be updated with the new value.

       Tcl_LinkVar uses variable traces to keep the Tcl variable named by varName in sync with the C variable at
       the address given by addr.

       Int,  double,  boolean  and char * variables are supported.  You can make your linked variables read only
       from the Tcl side, as well.  Please note that the C variables  must  continually  exist  while  they  are
       linked,  in  other  words, linking "automatic" C variables, those created on the stack while a routine is
       being executed and destroyed afterwards, will result in a malfunctioning program at best and  a  coredump
       or more at worst.

       For more information, please examine the LinkVar(3) manual page in the core Tcl distribution.

ADDING NEW MATH FUNCTIONS TO TCL

       As  of  Tcl  version  7.0,  math  functions  such  as  sin,  cos,  etc, are directly supported within Tcl
       expressions.  These obsolete the  Extended  Tcl  commands  that  provided  explicit  commands  for  these
       functions  for  many,  many  releases, although procs equivalencing the old TclX commands to the new math
       functions are still provided for backwards compatibility.

       New math functions can be added  to  Tcl,  or  existing  math  functions  can  be  replaced,  by  calling
       Tcl_CreateMathFunc.

ACCESSING AND MANIPULATING THE RANDOM NUMBER GENERATOR

       Prior to Tcl version 8.0, the Tcl core did not provide access to a random number generator, but TclX did,
       through  its  random  command.  As of Tcl version 8.0, access to a random number generator is provided by
       baseline Tcl through the new math functions, rand and srand.

       The TclX random command is still available -- it has some useful capabilities not  directly  provided  by
       the new baseline functions.

       For more information on adding your own math functions to Tcl, please study the CrtMathFnc(3) manual page
       in the core Tcl distribution.

CONVERTING FILENAMES TO NATIVE FORM AND PERFORMING TILDE SUBSTITUTIONS

       The  Tcl_TranslateFileName  function is available to C extension writers to translate filenames to a form
       suitable for use by the local operating system.  It converts network names to their native form,  and  if
       the name starts with a ``~'' character, the function returns a new string where the name is replaced with
       the home directory of the given user.

       For more information please consult the Translate(3) manual page in the core Tcl distribution.

SETTING THE RECURSION LIMIT

       Tcl  has  a  preset  recursion  limit  that limits the maximum allowable nesting depth of calls within an
       interpreter.  This is useful for detecting infinite recursions before other limits such  as  the  process
       memory limit or, worse, available swap space on the system, run out.

       The default limit is just a guess, however, and applications that make heavy use of recursion may need to
       call  Tcl_SetRecursionLimit  to  raise this limit.  For more information, please consult the SetRecLmt(3)
       manual page in the core Tcl distribution.

HANDLING SIGNALS FROM TCL EXTENSIONS

       If an event such as a signal occurs while a Tcl script is being executed, it isn't safe to do much in the
       signal handling routine -- the Tcl environment cannot be safely manipulated  at  this  point  because  it
       could  be  in  the  middle  of  some  operation, such as updating pointers, leaving the interpreter in an
       unreliable state.

       The only safe approach is to set a flag indicating that the event occurred, then handle the  event  later
       when the interpreter has returned to a safe state, such as after the current Tcl command completes.

       The  Tcl_AsyncCreate,  Tcl_AsyncMark,  Tcl_AsyncInvoke,  and  Tcl_AsyncDelete  functions  provide  a safe
       mechanism for dealing with signals and other asynchronous events.  For more information  on  how  to  use
       this capability, please refer to the Async(3) manual page in the core Tcl distribution.

       Note  that  Extended  Tcl  provides  built-in  support  for  managing signals in numerous ways, including
       generating them with alarm(2) and kill(2), ignoring them, trapping them, getting, setting,  blocking  and
       unblocking  them.  You can cause specific code to execute at a safe point after a signal occurs, or cause
       a Tcl error backtrace on one's occurrence.  For more information, please examine the TclX documentation.

PARSING BACKSLASH SEQUENCES

       The Tcl_Backslash function is called to parse Tcl backslash sequences.  These backslash sequences are the
       usual sort that you see in the C programming language, such as \n for newline,  \r  for  return,  and  so
       forth.   Tcl_Backslash parses a single backslash sequence and returns a single character corresponding to
       the backslash sequence.

       For more info on this call, look at the Backslash(3) manual page  in  the  core  Tcl  distribution.   For
       information  on  the valid backslash sequences, consult the summary of Tcl language syntax, Tcl(n) in the
       same distribution.

HASH TABLES

       Hash tables provide Tcl with a high-performance facility for looking  up  and  managing  key-value  pairs
       located  and  maintained in memory.  Tcl uses hash tables internally to locate procedure definitions, Tcl
       variables, array elements, file handles and so forth.  Tcl makes the hash table functions accessible to C
       extension writers as well.

       Hash tables grow automatically to maintain efficiency,  rather  than  exposing  the  table  size  to  the
       programmer  at  allocation  time,  which  would  needlessly  add  complexity to Tcl and would be prone to
       inefficiency due to the need to guess the number of items that will go into the table, and the  seemingly
       inevitable growth in amount of data processed per run over the useful life of the program.

       For more information on hash tables, please consult the Hash(3) manual page in the core Tcl distribution.

TRACING VARIABLE ACCESSES

       The  C  extension writer can arrange to have a C routine called whenever a Tcl variable is read, written,
       or unset.  Variable traces are the mechanism by which Tk toolkit widgets such as radio and  checkbuttons,
       messages  and  so forth update without Tcl programmer intervention when their data variables are changed.
       They are also used by the routine that links Tcl and C variables, Tcl_LinkVar, described above.

       Tcl_TraceVar is called to establish a variable trace.  Entire arrays and individual array elements can be
       traced as well.  If the programmer already has an array name  in  one  string  and  a  variable  name  in
       another,  Tcl_TraceVar2  can be called.  Calls are also available to request information about traces and
       to delete them.

       For more  information  on  variable  traces,  consult  the  TraceVar(3)  manual  page  in  the  core  Tcl
       distribution.

TRACING TCL EXECUTION

       Tcl  has  the  ability to call C routines each time it executes a Tcl command, up to a specified depth of
       nesting levels.  The command Tcl_CreateTrace creates an execution trace; Tcl_DeleteTrace deletes it.

       Command tracing is used in Extended Tcl to implement the cmdtrace  Tcl  command,  a  useful  command  for
       debugging Tcl applications.

       For  complete  information  on execution tracing, please look at the CrtTrace(3) manual pages in the core
       Tcl distribution.

EVALUATING TCL EXPRESSIONS FROM C

       Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBool, and  Tcl_ExprString  all  take  string  arguments  and,  when
       called, evaluate those strings as Tcl expressions.  Depending on the routine called, the result is either
       a  C  long,  a  double,  a  boolean  (int  with  a  value  of  0  or  1), or a char * (obtainable through
       Tcl_GetResult).

       To take advantage of the performance gains available  through  the  bytecode  compiler,  Tcl_ExprLongObj,
       Tcl_ExprDoubleObj,  Tcl_ExprBoolObj,  and  Tcl_ExprObj  all take an object containing an expression to be
       evaluated (rather than a string.)  The result is that bytecode-compiled version of the expression will be
       kept in the object, alongside the string representation.  If the expression is evaluated  again,  without
       being changed, it does not have to be recompiled... a major performance win.

       For complete information on evaluating Tcl expressions from C, you are invited to examine the ExprLong(3)
       and ExprLongObj(3) manpages in the core Tcl distribution.

PATTERN MATCHING

       The   Tcl_StringMatch  function  can  be  called  to  see  if  a  string  matches  a  specified  pattern.
       Tcl_StringMatch is called by the Tcl string match command, so the format for patterns is identical.   The
       pattern format is similar to the one used by the C-shell; string(n) describes this format.

       More  information  about  Tcl_StringMatch  is  available  in  the  StrMatch(3)  manpage  in  the core Tcl
       distribution.

REGULAR EXPRESSION PATTERN MATCHING

       Tcl_RegExpMatch  can  be  called  to  determine  whether  a  string   matches   a   regular   expression.
       Tcl_RegExpMatch is used internally by the regexp Tcl command.

       As  regular expressions are typically "compiled" before use, a fairly involved process, Tcl also supports
       routines that separate the compilation of an expression from its use:  Tcl_RegExpCompile, Tcl_RegExpExec,
       and Tcl_RegExpRange.  If an expression is going to be matched many times,  doing  the  compile  once  and
       caching  the compiled regular expression result, then reusing the cached version by using Tcl_RegExpExec,
       can be a significant performance win.

       For more information on this function, please consult the RegExp(3) manpage in the core Tcl distribution.

MANIPULATING TCL LISTS FROM C EXTENSIONS

       The C extension writer often needs to create, manipulate and  decompose  Tcl  lists.   Tcl_SplitList  and
       Tcl_Merge  used to be the only way to parse strings into lists and vice versa.  As of Tcl 8, lists can be
       parsed and assembled, object-style, using Tcl_ListObjGetElements and Tcl_SetListObj, and  friends.   Once
       again  the  "win"  of  using  object-system-based list manipulation, instead of the previous string based
       routines, is that the parsing of a string in an object to a list is cached in the object  structure,  the
       same  as  with  integers and floating point numbers, compiled procedures, etc.  The next time this string
       needs to be looked at as a list, if the contents of the string have not changed, the string does not have
       to be parsed.

       In the author's experience, working with  an  admittedly  degenerate  test  whereby  we  iterated  rather
       inefficiently  across  a  6,000-element  list,  a  speedup factor of more than 2500 was obtained over the
       previous non-object-based version of Tcl.

       For more information on these commands, please consult  the  ListObj(3)  manual  page  in  the  core  Tcl
       distribution.

CONCATENATING STRINGS

       Tcl_ConcatObj  concatenates  the  string representation of zero or more objects into a single new object.
       The elements of the new string are space-separated.  Tcl_Concat does  the  same  thing  for  strings,  as
       Tcl_ConcatObj does for objects.

       Concatenating  strings  is  similar  to  constructing  lists  from  them,  except  that Tcl_ConcatObj and
       Tcl_Concat do not attempt to make the resulting string into a valid Tcl list.

       Tcl_Concat is documented in the Concat(3) manpage, and Tcl_ConcatObj in the tringObj manpage, both in the
       core Tcl distribution.

DETECTING WHETHER OR NOT YOU HAVE A COMPLETE COMMAND

       C routines that collect data to form a command to be passed to Tcl_Eval often need a way to tell  whether
       they  have  a  complete command already or whether they need more data.  (Programs that read typed-in Tcl
       input such as Tcl shells need this capability, for instance.)  Tcl_CommandComplete can be  used  to  tell
       whether or not you have a complete command.

       For more information examine CmdCmplt(3) in the core Tcl distribution.

RECORDING COMMANDS FOR COMMAND HISTORY

       Tcl  has  a  history  mechanism  that is accessed from Tcl through the history command.  If you want your
       extension to propagate commands into the command history, you should  call  Tcl_RecordAndEvalObj  (object
       system) or Tcl_RecordAndEval (old system),

       These  commands  work  like Tcl_EvalObj and Tcl_Eval, respectively, except that these versions record the
       command as well as executing it.

       Tcl_RecordAndEval and Tcl_RecordAndEvlObj should only be called  with  user-entered  top-level  commands,
       since the history mechanism exists to allow the user to easily access, edit and reissue previously issued
       commands.

       For  complete  information  on  these  functions, please examine the RecordEval.3 and RecEvalObj.3 manual
       pages in the core Tcl distribution.

CONVERTING FLOATING POINT VALUES TO STRINGS

       The Tcl object system's Tcl_GetDoubleFromObj and  Tcl_SetDoubleObj  use  Tcl  objects,  rather  than  the
       strings used by Tcl_PrintDouble, and convert, when necessary, an ASCII string to a double and back again.

       These  routines  ensure  that  the  string  output  will continue to be interpretable as a floating point
       number, rather than an integer, by always putting a ``.'' or  ``e''  into  the  string  representing  the
       number.

       The precision of the output string is controlled by the Tcl tcl_precision variable.

       For  complete  information on these routines, please examine DoubleObj(3) and PrintDbl(3) in the core Tcl
       distribution.

CREATING CHILD PROCESSES AND PIPELINES FROM C

       Tcl_OpenCommandChannel provides a C-level interface to  the  exec  and  open  commands.   The  child  (or
       pipeline  of  children) can have its standard input, output and error redirected from files, variables or
       pipes.  To understand the meaning of the redirection symbols understood by this  function,  look  at  the
       exec(n) Tcl command.  For complete information on Tcl_OpenCommandChannel, please examine OpenFileChnl(3).

ACCESSING TCL FILEHANDLES FROM C

       On  Posix/Unix  systems,  Tcl  filehandles passed to your C extension can be translated to a Posix FILE *
       structure using the Tcl_GetOpenFile function, documented in GetOpnFl.3.

MANAGING BACKGROUND PROCESS TERMINATION AND CLEANUP

       When a Posix system does a fork to create a new process, the process ID of the child is returned  to  the
       caller.   After the child process exits, its process table entry (and some other data associated with the
       process) cannot be reclaimed by the operating system until a call to waitpid,  or  one  of  a  couple  of
       other, similar system calls, has been made by the parent process.

       The  C extension writer who has created a subprocess, by whatever mechanism, can turn over responsibility
       for detecting the processes' termination and calling waitpid  to  obtain  its  exit  status,  by  calling
       Tcl_DetachPids on it.

       Tcl_ReapDetachedProcs  is  the C routine that will detect the termination of any processes turned over to
       Tcl, permitting the processes to be fully reclaimed by the operating system.  It is usually not necessary
       to call Tcl_ReapDetachedProcs, as it is called automatically every time exec is performed.

       For complete information on these routines, please look at DetachPids(3) in the core Tcl distribution.

FOR MORE INFORMATION

       In addition to the documentation referenced above, you can learn a lot by studying the source code of the
       commands added by Tcl, Tk and Extended Tcl, etc.  The comp.lang.tcl Usenet newsgroup is read by  hundreds
       of  thousands  of  Tcl  people.  A number of Frequently Asked Questions (FAQs) about Tcl are posted there
       periodically.  The newsgroup is a good place to ask questions (after you've made sure they're not already
       answered in the FAQ ;-)

       Finally, if you have interactive Internet access, you can ftp to ftp://ftp.neosoft.com/pub/tcl, the  site
       for  contributed  Tcl  sources.   This  site contains quite a few extensions, applications, and so forth,
       including several object-oriented extension packages.

       If   you   have   access   via   the   world-wide   web,   check   out   the   Sun   Microsystems    site
       (http://sunscript.sun.com), the contributed sources archive website (http://www.neosoft.com/tcl), and the
       homepage for Extended Tcl (http://www.neosoft.com/tclx).

AUTHORS

       Extended Tcl was created by Karl Lehenbauer (karl@neosoft.com) and Mark Diekhans (markd@grizzly.com).

Tcl                                                                                       Command Writing(3tclx)