Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
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 al-
     ready fluent in the C programming language and that you have built and  in-
     stalled 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 in-
     teger, will now maintain a machine-code integer representation, if an inte-
     ger representation has been needed.  Using these objects is much more effi-
     cient 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 pro-
     grammer 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 hav-
     ing 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  back-
     wards 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  ar-
     ray 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  proce-
     dures,  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 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 ar-
     gument count, objc, and a newline is output to terminate the line -- a sim-
     ple ``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  Ob-
     jects.  If your C routine wants to look at one of those arguments as an in-
     teger,  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_Get-
     StringFromObj  is	called	to obtain a textual representation of an object.
     Additional routines are available to fetch the representation of a data el-
     ement as other data  types.   Tcl_GetBooleanFromObj,  Tcl_GetDoubleFromObj,
     Tcl_GetIntFromObj,  Tcl_GetLongFromObj,  and Tcl_GetIndexFromObj, fetch ob-
     ject 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  oc-
     curs.    (For  more  information  on these routines, please look at the Ob-
     ject(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 writ-
     ing small results directory into the  interpreter's  result  buffer  is  no
     longer  used,  for example.  The notion of having to tell Tcl whether a re-
     sult 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  ex-
     tension  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  ava-
     iable  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 conver-
     sions 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 bi-
     nary data instrinsically), handles need to be used.  Handles  will  be  de-
     scribed 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 it-
     self, 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  re-
     sponse to the common mistake of being called with a wrong number.

     Tcl_GetIntFromObj	is used to fetch the integer values of the remaining ar-
     guments.  If any fail to be converted, we return a Tcl error.  If an inter-
     preter 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	contain-
     ing 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 re-
     verse.

     Once lreverse has determined that it has received the correct number of ar-
     guments, 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, pass-
     ing 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 rou-
     tine.

     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 inter-
     preter.  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  ar-
     bitrarily	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  represen-
     tation 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  capa-
     bilites 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  as-
     sociated  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 in-
     terpreters) 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  multi-
     ple 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_CreateObjCom-
     mand.

     When  your command is called from Tcl, the ClientData pointer you passed to
     Tcl_CreateObjCommand will be passed to your C routine through  the  Client-
     Data 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  struc-
     ture.   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 sup-
     port 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  Ex-
     tended  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	enhance-
     ments 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-func-
     tions),  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 exam-
     ple,  in Tk, creating a checkbutton (checkbutton .b) creates a new Tcl com-
     mand (.b), that has methods to configure the button, select, deselect, tog-
     gle 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 sys-
     tem 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 alloca-
     tion  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  try-
     ing 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 tech-
     nology 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 li-
     braries 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  sys-
     tem,  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 applica-
     tion-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  ap-
     plication-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  vari-
     ables 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 over-
     ride 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 al-
     located 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  func-
     tions  upon the deletion of an interpreter as well.  To facilitate this ac-
     tivity, Tcl provides the ability to perform a function callback when an in-
     terpreter is deleted.  To arrange for a C function to be  called  when  the
     interpreter is deleted, call Tcl_CallWhenDeleted from your application ini-
     tialization  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_Get-
     StringResult,  if	you  want  a  string  representation  of  the result, or
     Tcl_GetObjResult if you want the object.  (The use of interp->result to ac-
     cess the result string has been deprecated.)

     The Tcl object system adds Tcl_EvalObj and Tcl_GlobalEvalObj.  The  differ-
     ence 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 ma-
     jor performance improvement in your code, when the code is executed repeat-
     edly (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_Ob-
     jSetVar2 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 per-
     formance boosts from "lazy" type conversion and the binary  data  capabili-
     ties, the arguments containing the variable name, or the array name and el-
     ement 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 ex-
     tensions  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 subrou-
     tine.  It works just like Tcl_ObjGetVar2, except the one  or  two	variable
     name arguments are specified as strings, and the routine takes care of mak-
     ing 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  ob-
     tain the string representation first.

     For  complete  information  on these functions, please refer to the ObjSet-
     Var(3) and SetVar(3) manual pages in the doc directory of the core Tcl dis-
     tribution.

LINKING TCL VARIABLES TO C VARIABLES
     Tcl_LinkVar and Tcl_UnlinkVar can be used to automatically keep  Tcl  vari-
     ables 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 mal-
     functioning 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 re-
     leases, 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 ver-
     sion  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  capabili-
     ties 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  sys-
     tem.   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 infi-
     nite 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 environ-
     ment cannot be safely manipulated at this point because it could be in  the
     middle  of  some  operation,  such as updating pointers, leaving the inter-
     preter 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 asyn-
     chronous 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),  ignor-
     ing  them,  trapping  them, getting, setting, blocking and unblocking them.
     You can cause specific code to execute at a safe point after a  signal  oc-
     curs,  or cause a Tcl error backtrace on one's occurrence.  For more infor-
     mation, 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 program-
     ming  language,  such  as	\n  for  newline,  \r  for return, and so forth.
     Tcl_Backslash parses a single backslash sequence and returns a single char-
     acter 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  distribu-
     tion.

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 el-
     ements, file handles and so forth.  Tcl makes the hash table functions  ac-
     cessible 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 vari-
     ables, 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_Trace-
     Var2 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 com-
     mand, a useful command for debugging Tcl applications.

     For complete information on execution tracing,  please  look  at  the  Crt-
     Trace(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  expres-
     sions.   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_Ex-
     prObj  all  take an object containing an expression to be evaluated (rather
     than a string.)  The result is that bytecode-compiled version  of	the  ex-
     pression  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 in-
     vited 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  com-
     mand, so the format for patterns is identical.  The pattern format is simi-
     lar to the one used by the C-shell; string(n) describes this format.

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

REGULAR EXPRESSION PATTERN MATCHING
     Tcl_RegExpMatch can be called to determine whether a string matches a regu-
     lar  expression.  Tcl_RegExpMatch is used internally by the regexp Tcl com-
     mand.

     As regular expressions are typically "compiled" before use,  a  fairly  in-
     volved 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 manip-
     ulation, 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)  man-
     ual page in the core Tcl distribution.

CONCATENATING STRINGS
     Tcl_ConcatObj  concatenates  the  string representation of zero or more ob-
     jects 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 of-
     ten 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_Recor-
     dAndEval (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 RecordE-
     val.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 inter-
     pretable 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_OpenCommandChan-
     nel, 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) can-
     not 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 re-
     claimed 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(TCL)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=ObjCmdWrite&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help