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, win-
       dow manager, etc.  Experienced extension	writers	may find  this	manual
       helpful	in rewriting their applications	to use the new Tcl object sys-
       tem.  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  dis-
       tribution,  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 na-
       tive  datatypes.	 For example, an object	containing a string consisting
       of an integer, will now maintain	a machine-code integer representation,
       if an integer representation has	been needed.  Using these  objects  is
       much  more  efficient  than using the older-style Tcl strings, although
       the older style is still	(currently) supported.

       Although	the object system has almost no	effect at all on how  the  Tcl
       programmer uses Tcl, the	object system's	C interfaces to	strings, inte-
       gers, lists, etc., have changed considerably.  While converting a pack-
       age  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 com-
       piler (which keeps Tcl from having to continually reparse code it is to
       execute)	yield Tcl programs that	routinely execute several  times  more
       quickly	than  with  previous  versions (Tcl 7 and before), and in some
       cases run as much as 2500 (!) times faster than before.

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

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

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

	   #include "tcl.h"

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

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

       The client data pointer will be described later.

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

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

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

       In  the above example, all of the arguments are output with a space be-
       tween 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  sim-
       plicity.	  Of  course  in production code you would want	to use the Tcl
       filesystem interfaces.  See GetFile(3) and friends  for	more  informa-
       tion.

       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 represen-
       tation  of  the	object that you	need.  In the earlier example, for in-
       stance, Tcl_GetStringFromObj is called to obtain	a textual  representa-
       tion of an object.  Additional routines are available to	fetch the rep-
       resentation  of a data element as other data types.  Tcl_GetBooleanFro-
       mObj, Tcl_GetDoubleFromObj, Tcl_GetIntFromObj, Tcl_GetLongFromObj,  and
       Tcl_GetIndexFromObj, fetch object representations  of  Tcl  strings  as
       booleans,  double-precision  floating point, integer, long integer, and
       lists, among others.

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

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

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

	       Tcl_Obj *obj;

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

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

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

	       Tcl_Obj *resultObj;

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

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

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

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

       The object system has simplified, to some degree, the task of  validat-
       ing  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 ver-
       ify that	it has the right number	of arguments.

       The  act	of trying to use, say, a string	as an integer, implicitly per-
       forms 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_ER-
       ROR  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 fu-
       tures 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'' com-
       mand text itself, objv[0], and a	pointer	to at least one	object to com-
       pare 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 appropri-
       ate error message about the conversion failure will be left in the  re-
       sult, 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 func-
       tion should just	return a status	value.	For example, end-of-file  dur-
       ing  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 Ex-
       tended 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 con-
       taining 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 el-
       ements.

       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 com-
       mand 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 op-
       tional 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	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	avail-
       able with Tcl 7.0.  Dynamic strings, or	DStrings,  provide  a  way  to
       build up	arbitrarily long strings through a repeated process of append-
       ing  information	to them.  DStrings reduce the amount of	allocating and
       copying required	to add information to a	string.	  Further,  they  sim-
       plify 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  pos-
       sible  by  the  lazy  conversion	of an object's representation from one
       datatype	to another does	not come into  play  much  while  constructing
       strings as the string representation is always available	either without
       any  type conversion or where type conversion would be necessary	in any
       case as a string	representation of the object is	required when  strings
       are being constructed by	concatenation, etc.

       It should be noted, however, that the C level string manipulation capa-
       bilites of objects, such	as Tcl_AppendToObj and Tcl_AppendStringsToObj,
       are often plenty	enough for what	you need to do.	 For complete informa-
       tion  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 envi-
       ronment (where a	single program has created and is making use of	multi-
       ple Tcl interpreters) for the C routines	to maintain any	permanent data
       they need on a per-interpreter basis.  If needed	static data was	simply
       declared	 static	 in C, you will	probably have reentrancy problems when
       you work	with multiple interpreters.

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

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

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

       It is important to note that the	Tcl extensions in the tclX8.0.0	direc-
       tory 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	repre-
       sentable	as a string within Tcl,	for example a pointer to a  complex  C
       data  structure.	  It is	not a good idea	to try to pass pointers	around
       within Tcl as strings by	converting them	to and	from  hex  or  integer
       representations,	 for  example.	It is too easy to mess one up, and the
       likely outcome of doing that is a core dump.

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

       Handles	have  proven  so useful	that, since TclX release 6.1a, general
       support has been	available to help create and manipulate	them.  Many of
       these capabilities have migrated	into baseline Tcl.  If you have	a sim-
       ilar need, you might like to use	the handle routines documented in Han-
       dles(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 some-
       thing 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 writ-
       ing (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, of-
       fers handle-like	capabilities as	well as	some neat additional capabili-
       ties.   That  is	to create a new	Tcl command, from C, that uses Client-
       Data to keep a "handle" on its complex underlying data structure.  Then
       by having that command look at its second argument for what it is to do
       (its sub-functions), you	get these nice methods,	where you have several
       additional sub-commands that don't pollute  the	global	namespace  and
       only  work  on (and are available with) the objects (new	commands) they
       are relevant to.	 For example, in Tk, creating a	checkbutton (checkbut-
       ton .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 ob-
       ject system for Tcl, objects that you define in Tcl will	be highly com-
       patible in terms	of their command interfaces and	configuration  manage-
       ment  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 allo-
       cated piece of memory.  This will usually result	in a core dump or mem-
       ory 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 prob-
       lems.   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  exe-
       cutable	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	simplify a Tcl instal-
       lation,	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  nu-
       ances  of the compiler and linker arguments automatically when the con-
       figure script is	run.  If you are building a package that you  plan  to
       make  generally available, we strongly recommend	that you use GNU auto-
       conf (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 note-
       book 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  ap-
       plication-specific  init	 function  which  you  create.	 This function
       should take the address of the interpreter it should install  its  com-
       mands 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  ap-
       plication named cute one	would create a Cute_Init routine that expected
       a  Tcl_Interp  pointer  as  an  argument, and add the following code to
       Tcl_AppInit:

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

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

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

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

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

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

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

EXTENDED TCL EXIT
       When Extended Tcl exits,	Tcl_DeleteInterp may be	called to free	memory
       used  by	 Tcl --	normally, this is only called if TCL_MEM_DEBUG was de-
       fined, 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  re-
       peatedly	 without  ever	freeing	it, or at least	without	always freeing
       it.

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

EXECUTING TCL CODE FROM	YOUR C EXTENSION
       Suppose	you  are in the	middle of coding a C extension and you realize
       that you	need some operation performed, one that	would be  simple  from
       Tcl,  but  possibly  excruciating  to do	directly in C.	Tcl provides a
       number of C-level interfaces whereby you	can cause Tcl code to be  exe-
       cuteed.	 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 representa-
       tion  of	 the result, or	Tcl_GetObjResult if you	want the object.  (The
       use of interp->result to	access the result string has been deprecated.)

       The Tcl object system adds Tcl_EvalObj and Tcl_GlobalEvalObj.  The dif-
       ference 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 byte-
       code compiler to	compile	the code being evaluated and save the compiled
       code with the data structure, in	an implementation-dependent manner.

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

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

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

       While  the  fact	that Tcl_ObjGetVar2 retrieves Tcl objects, rather than
       strings,	is critical for	the object system to be	able  to  provide  the
       performance  boosts from	"lazy" type conversion and the binary data ca-
       pabilities, 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  usu-
       ally  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_Unset-
       Var2 functions.	There are  currently  (as  of  8.0)  no	 object-system
       equivalents,  so	 in the	rare case where	you have the name of the vari-
       able 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 Ob-
       jSetVar(3) and SetVar(3)	manual pages in	the doc	directory of the  core
       Tcl distribution.

LINKING	TCL VARIABLES TO C VARIABLES
       Tcl_LinkVar  and	 Tcl_UnlinkVar	can  be	used to	automatically keep Tcl
       variables synchronized with corresponding  C  variables.	  Once	a  Tcl
       variable	 has been linked to a C	variable with Tcl_LinkVar, anytime the
       Tcl variable is read, the value of the C	variable is converted (if nec-
       essary) and returned, and when the Tcl variable is written, the C vari-
       able will be updated with the new value.

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

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

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

ADDING NEW MATH	FUNCTIONS TO TCL
       As of Tcl version 7.0, math functions such as sin, cos,	etc,  are  di-
       rectly  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 compatibil-
       ity.

       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 ran-
       dom  number generator, but TclX did, through its	random command.	 As of
       Tcl version 8.0,	access to a random number  generator  is  provided  by
       baseline	Tcl through the	new math functions, rand and srand.

       The  TclX random	command	is still available -- it has some useful capa-
       bilities	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  operat-
       ing system.  It converts	network	names to their native form, and	if the
       name  starts  with a ``~'' character, the function returns a new	string
       where the name is replaced with the home	directory of the given user.

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

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

       The  default limit is just a guess, however, and	applications that make
       heavy use of recursion may need to call Tcl_SetRecursionLimit to	 raise
       this limit.  For	more information, please consult the SetRecLmt(3) man-
       ual 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 exe-
       cuted, it isn't safe to do much in the signal handling routine  --  the
       Tcl  environment	 cannot	be safely manipulated at this point because it
       could be	in the middle of some operation, such  as  updating  pointers,
       leaving the interpreter in an unreliable	state.

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

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

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

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

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

HASH TABLES
       Hash tables provide Tcl with a high-performance facility	for looking up
       and  managing  key-value	 pairs	located	and maintained in memory.  Tcl
       uses hash tables	internally to locate procedure definitions, Tcl	 vari-
       ables,  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  ex-
       posing the table	size to	the programmer at allocation time, which would
       needlessly add complexity to Tcl	and would be prone to inefficiency due
       to  the	need to	guess the number of items that will go into the	table,
       and the seemingly inevitable growth in amount of	data processed per run
       over the	useful life of the program.

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

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

       Tcl_TraceVar is called to establish a variable  trace.	Entire	arrays
       and individual array elements can be traced as well.  If	the programmer
       already has an array name in one	string and a variable name in another,
       Tcl_TraceVar2  can  be called.  Calls are also available	to request in-
       formation 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 com-
       mand, up	to a specified depth of	nesting	levels.	 The command  Tcl_Cre-
       ateTrace	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  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 ex-
       pressions.  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	 byte-
       code compiler, Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBoolObj, and
       Tcl_ExprObj all take an object containing an expression to be evaluated
       (rather	than  a	string.)  The result is	that bytecode-compiled version
       of the expression will be kept in the object, alongside the string rep-
       resentation.  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 compila-
       tion 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 expres-
       sion 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-sys-
       tem-based list manipulation, instead of the previous string based  rou-
       tines, 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-ob-
       ject-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,  ex-
       cept  that  Tcl_ConcatObj and Tcl_Concat	do not attempt to make the re-
       sulting string into a valid Tcl list.

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

DETECTING WHETHER OR NOT YOU HAVE A COMPLETE COMMAND
       C routines that collect data to form a command to be passed to Tcl_Eval
       often need a way	to tell	whether	they have a complete  command  already
       or whether they need more data.	(Programs that read typed-in Tcl input
       such  as	 Tcl shells need this capability, for instance.)  Tcl_Command-
       Complete	can be used to tell whether or not you have  a	complete  com-
       mand.

       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 his-
       tory command.  If you want your extension to  propagate	commands  into
       the  command history, you should	call Tcl_RecordAndEvalObj (object sys-
       tem) or Tcl_RecordAndEval (old system),

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

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

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

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  con-
       vert, 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_preci-
       sion 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	 stan-
       dard 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	mecha-
       nism, can turn over responsibility for detecting	the processes'	termi-
       nation  and  calling  waitpid  to  obtain  its  exit status, by calling
       Tcl_DetachPids on it.

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

       For complete information	on these  routines,  please  look  at  Detach-
       Pids(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  Ex-
       tended  Tcl,  etc.   The	comp.lang.tcl Usenet newsgroup is read by hun-
       dreds of	thousands of Tcl people.  A number of Frequently  Asked	 Ques-
       tions (FAQs) about Tcl are posted there periodically.  The newsgroup is
       a  good	place to ask questions (after you've made sure they're not al-
       ready 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 Microsys-
       tems 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+14.3.quarterly>

home | help