Home Man
Search
Today's Posts
Register

Linux & Unix Commands - Search Man Pages

RedHat 9 (Linux i386) - man page for tclcommandwriting (redhat section 3)

Command Writing(TCL)							     Command Writing(TCL)

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  inter-
       nally.	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 consist-
       ing 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 consider-
       ably.  While converting a package to use the new system can be a lot of work, the combina-
       tion  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 ver-
       sion 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  inter-
       faces  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 inter-
       preter 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_CreateIn-
       terp 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 inter-
       preter.	(For more information on creating and deleting interpreters, please  examine  the
       CrtInterp(3)  manpage  in  the  core Tcl distribution.  For information on creating inter-
       preters 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 exam-
       ple, 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 oth-
       ers.

       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 signifi-
       cantly 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 con-
       tains 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 con-
       version 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 CrtCom-
       mand(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 allocat-
       ing  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 rep-
       resentation 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 conver-
       sion 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_Cre-
       ateObjCommand  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_CreateObj-
       Command 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 Client-
       Data 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 out-
       come 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 possi-
       ble.  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 han-
       dle by checking the the file text is present, then converting the file number to an  inte-
       ger  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  cur-
       rently 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 checkbut-
       ton (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 configu-
       ration management with objects you create in C using the the command-and-ClientData  tech-
       nique  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  mem-
       ory.   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, sup-
       port 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  sim-
       plify  a  Tcl  installation, because only one copy of Tcl is required, rather than a hode-
       podge 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 fore-
       warned 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 func-
       tion.  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  suc-
       cessfully, 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 appli-
       cation'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  declara-
       tions 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 -- nor-
       mally, 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  func-
       tion  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_GetObjRe-
       sult  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 imple-
       mentation-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 vari-
       able  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  con-
       version	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 Set-
       Var(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 vari-
       ables read only from the Tcl side, as well.  Please note that the C variables must contin-
       ually  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 distribu-
       tion.

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  genera-
       tor,  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  Crt-
       MathFnc(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 file-
       names 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 distribu-
       tion.

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 lim-
       its  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 recur-
       sion  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 point-
       ers, 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  cur-
       rent 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  infor-
       mation 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, get-
       ting, 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 distribu-
       tion.  For information on the valid backslash sequences, consult the summary of	Tcl  lan-
       guage 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 inter-
       vention 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 speci-
       fied 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 byte-
       code-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 per-
       formance 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_ListOb-
       jGetElements and Tcl_SetListObj, and friends.  Once again the "win" of  using  object-sys-
       tem-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_Conca-
       tObj 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 man-
       page, 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  ver-
       sions 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 RecEval-
       Obj.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 float-
       ing  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 sys-
       tem.  It is usually not necessary to call Tcl_ReapDetachedProcs, as it is called automati-
       cally 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(TCL)


All times are GMT -4. The time now is 11:24 PM.

Unix & Linux Forums Content Copyrightę1993-2018. All Rights Reserved.
UNIX.COM Login
Username:
Password:  
Show Password