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. C programming
information can also be found in the *.3 manual pages in the
doc directory of the Berkeley distribution, and in the *.3
manpages in the man directory of Extended Tcl.
WRITING TCL EXTENSIONS IN C
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 pointers to character
strings containing the Tcl arguments to the command.
A simple Tcl extension in C is now presented, and described
below:
#include "tcl.h"
int App_EchoCmd(clientData, interp, argc, argv)
void *clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
int i;
for (i = 1; i < argc; i++) {
printf("%s",argv[i]);
if (i < argc - 1) printf(" ");
}
printf("\n");
return TCL_OK;
}
The client data pointer will be described later.
The interpreter pointer is the ``key'' to an interpreter.
It is returned by Tcl_CreateInterp and is used extensively
within Tcl, and will be by your C extensions. The data
structure pointed to by the interpreter pointer, and all of
the subordinate structures that branch off of it, make up a
Tcl interpreter, which includes all of the currently defined
procedures, commands, variables, arrays and the execution
state of that interpreter. (For more information on
creating and deleting interpreters, please examine the
CrtInterp(3) manpage in the Berkeley 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 Berkeley Tcl.)
The argument count and pointer to an array of pointers to
textual arguments is handled by your C code in the same
manner that you would use in writing a C main function --
the 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 argv array. Similar to a C main, the
first argument (argv[0]) is the name the routine was called
as (in a main, the name the program was invoked as).
In the above example, all of the arguments are output with a
space between each one by looping through argv from one to
the argument count, argc, and a newline is output to
terminate the line -- an ``echo'' command.
All arguments from a Tcl call to a Tcl C extension are
passed as strings. If your C routine expects certain
numeric arguments, your routine must first convert them
using the Tcl_GetInt or Tcl_GetDouble function, Extended
Tcl's Tcl_GetLong or Tcl_GetUnsigned, or some other method
of your own devising. Likewise for converting boolean
values, Tcl_GetBoolean should be used. These routines
automatically leave an appropriate error message in the Tcl
interpreter's result buffer and return TCL_ERROR if a
conversion error occurs. (For more information on these
routines, please look at the GetInt(3) manpage in the
Berkeley Tcl distribution.)
Likewise, if you program produces a numeric result, it
should return a string equivalent to that numeric value. A
common way of doing this is something like...
sprintf(interp->result, "%ld", result);
Writing results directly into the interpreter's result
buffer is only good for relatively short results. Tcl has a
function, Tcl_SetResult, which provides the ability for your
C extensions to return very large strings to Tcl, with the
ability to tell the interpreter whether it ``owns'' the
string (meaning that Tcl should delete the string when it's
done with it), that the string is likely to be changed or
overwritten soon (meaning that Tcl should make a copy of the
string right away), or that the string won't change (so Tcl
can use the string as is and not worry about it).
Understanding how results are passed back to Tcl is
essential to the C extension writer. Please study the
SetResult(3) manual page in the Tcl distribution.
Sophisticated commands should verify their arguments
whenever possible, both by examining the argument count, by
verifying that numeric fields are really numeric, that
values are in range (when their ranges are known), and so
forth.
Tcl is designed to be as bullet-proof as possible, in the
sense that no Tcl program should be able to cause Tcl to
dump core. Please carry this notion forward with your C
extensions by validating arguments as above.
ANOTHER C EXTENSION - THE MAX
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 three
arguments (the pointer to the ``max'' command text itself,
argv[0], and pointers to at least two arguments to compare
the values of).
This routine also shows the use of the programmer labor-
saving Tcl_AppendResult routine. See the Tcl manual page,
SetResult(3), for details. Also examine the calls
Tcl_AddErrorInfo, Tcl_SetErrorCode and Tcl_PosixError
documented in the Tcl manual page AddErrInfo(3).
int
Tcl_MaxCmd (clientData, interp, argc, argv)
char *clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
int maxVal = MININT;
int maxIdx = 1;
int value, idx;
if (argc < 3) {
Tcl_AppendResult (interp, "bad # arg: ", argv[0],
" num1 num2 [..numN]", (char *)NULL);
return TCL_ERROR;
}
for (idx = 1; idx < argc; idx++) {
if (Tcl_GetInt (argv[idx], 10, &Value) != TCL_OK)
return TCL_ERROR;
if (value > maxVal) {
maxVal = value;
maxIdx = idx;
}
}
Tcl_SetResult (interp, argv [maxIdx], TCL_VOLATILE);
return TCL_OK;
}
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 the open 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 Tcl's while, for and if,
and Extended Tcl's loop commands.
Note the call to Tcl_SetResult in the above command to set
the return value to Tcl. TCL_VOLATILE is used because the
memory containing the result will be freed upon the
function's return.
ANOTHER C EXTENSION - THE LREVERSE
In the command below, one list is passed as an argument, and
a list containing all of the elements of the list in reverse
order is returned. It is an error if anything other than
two arguments are passed (the pointer to the ``lreverse''
command text itself, argv[0], and a pointer to the list to
reverse.
Once lreverse has determined that it has received the
correct number of arguments, Tcl_SplitList is called to
break the list into an argc and argv array of pointers.
lreverse then operates on the array of pointers, swapping
them from lowest to highest, second-lowest to second-
highest, and so forth.
Finally Tcl_Merge is calleds to create a single new string
containing the reversed list and it is set as the result via
Tcl_SetResult. Note that TCL_DYNAMIC is used to tell
Tcl_SetResult that it now owns the string and it is up to
Tcl to free the string when it is done with it.
Note that it is safe to play around with the argv list like
this, and that a single call to ckfree can be made to free
all the data returned by Tcl_SplitList in this manner.
int
Tcl_LreverseCmd(notUsed, interp, argc, argv)
ClientData notUsed; /* Not used. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int listArgc, lowListIndex, hiListIndex;
char **listArgv;
char *temp, *resultList;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be
" list
return TCL_ERROR;
}
if (Tcl_SplitList(interp, argv[1], &listArgc, &listArgv) != TCL_OK) {
return TCL_ERROR;
}
for (lowListIndex = 0, hiListIndex = listArgc;
--hiListIndex > lowListIndex; lowListIndex++) {
temp = listArgv[lowListIndex];
listArgv[lowListIndex] = listArgv[hiListIndex];
listArgv[hiListIndex] = temp;
}
resultList = Tcl_Merge (listArgc, listArgv);
ckfree (listArgv);
Tcl_SetResult (interp, resultList, TCL_DYNAMIC);
return TCL_OK;
}
INSTALLING YOUR COMMAND
To install your command into Tcl you must call
Tcl_CreateCommand, passing it the pointer to the interpreter
you want to install the command into, the name of the
command, a pointer to the C function that implements the
command, a client data pointer, and a pointer to an optional
callback routine.
The client data pointer and the callback routine will be
described later.
For example, for the max function above (which,
incidentally, comes from TclX's tclXmath.c in the
TclX7.4/src directory):
Tcl_CreateCommand (interp, "max", Tcl_MaxCmd, (ClientData)NULL,
(void (*)())NULL);
In the above example, the max function is added to the
specified interpreter. The client data pointer and callback
function pointer are NULL. (For complete information on
Tcl_CreateCommand and its companion routine,
Tcl_CommandInfo, please examine the CrtCommand(3) command
page in the Berkeley Tcl distribution.)
DYNAMIC STRINGS
Dynamic strings are an important abstraction that first
became available with Tcl 7.0. Dynamic strings, or
DStrings, provide a way to build up arbitrarily long strings
through a repeated process of appending information to them.
DStrings reduce the amount of allocating and copying
required to add information to a string. Further, they
simplify the process of doing so. For complete information
on dynamic strings, please examine the DString(3) manual
page in the Berkeley Tcl distribution.
CLIENT DATA
The client data pointer provides a means for Tcl commands to
have data associated with them that is not global to the C
program nor included in the Tcl core. Client data is
essential in a multi-interpreter environment (where a single
program has created and is making use of multiple Tcl
interpreters) for the C routines to maintain any permanent
data they need on a per-interpreter basis. Otherwise there
would be reentrancy problems. Tcl solves this through the
client data mechanism. When you are about to call
Tcl_CreateCommand to add a new command to an interpreter, if
that command needs to keep some read/write data across
invocations, you should allocate the space, preferably using
ckalloc, then pass the address of that space as the
ClientData pointer to Tcl_CreateCommand.
When your command is called from Tcl, the ClientData pointer
you gave to Tcl_CreateCommand when you added the command to
that interpreter is passed to your C routine through the
ClientData pointer calling argument.
Commands that need to share this data with one another can
do so by using the same ClientData pointer when the commands
are added.
It is important to note that the Tcl extensions in the
tclX7.4/src directory have had all of their data set up in
this way. Since release 6.2, Extended Tcl has supported
multiple interpreters within one invocation of Tcl.
THEORY OF HANDLES
Sometimes you need to have a data element that isn't readily
representable as a string within Tcl, for example a pointer
to a complex C data structure. It is not a good idea to try
to pass pointers around within Tcl as strings by converting
them to and from hex or integer representations, for
example. It is too easy to mess one up, and the likely
outcome of doing that is a core dump.
Instead we have developed and made use of the concept of
handles. Handles are identifiers a C extension can pass to,
and accept from, Tcl to make the transition between what
your C code knows something as and what name Tcl knows it by
to be as safe and painless as possible. For example, the
stdio package 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, as of release 6.1a,
general support has been added for them. If you need a
similar capability, it would be best to use the handle
routines, documented in Handles(3) in Extended Tcl. We
recommend that you use a unique-to-your-package textual
handle coupled with a specific identifier and let the handle
management routines validate it when it's passed back. It
is much easier to track down a bug with an implicated handle
named something like file4 or bitmap6 than just 6.
TRACKING MEMORY CORRUPTION PROBLEMS
Occasionally you may write code that scribbles past the end
of an allocated piece of memory. The memory debugging
routines included in Tcl can help find these problems. See
Memory(TCL) for details.
INSTALLING YOUR EXTENSIONS INTO EXTENDED TCL
To add your extensions to Extended Tcl, you must compile
them and cause them to be linked with TclX. For the
routines to be linked into the tcl and wishx executables,
they must be referenced (directly or indirectly) from TclX.
For these extensions to be visible as Tcl commands, they
must be installed into Tcl with Tcl_CreateCommand.
Application-specific startup is accomplished by creating or
editing the Tcl_AppInit function. In Tcl_AppInit you should
add a call to an application-specific init function which
you create. This function should take the address of the
interpreter it should install its commands into, and it
should install those commands with Tcl_CreateCommand and do
any other application-specific startup that is necessary.
The naming convention for application startup routines is
App_Init, where App is the name of your application. For
example, to add an application named cute one would create a
Cute_Init routine that expected a Tcl_Interp pointer as an
argument, and add the following code to Tcl_AppInit:
if (Cute_Init (interp) == TCL_ERROR) {
return TCL_ERROR;
}
As you can guess from the above example, if your init
routine is unable to initialize, it should use
Tcl_AppendResult to provide some kind of useful error
message back to TclX, then return TCL_ERROR to indicate that
an error occurred. If the routine executed successfully, it
should return TCL_OK.
When you examine Tcl_AppInit, note that there is one call
already there to install an application -- the call to
TclX_Init installs Extended Tcl into the Tcl core.
MAKING APPLICATION INFORMATION VISIBLE FROM EXTENDED
TclX's infox command can return several pieces of
information relevant to Extended Tcl, including the
application's name, descriptive name, patch level and
version. Your application's startup can set these variables
to application-specific values. If it doesn't, they are
given default values for Extended Tcl.
To set these values, first be sure that you include either
tclExtend.h or tclExtdInt.h from the source file that
defines your init routine. This will create external
declarations for the variables. Then, set the variables in
your init route, for example:
tclAppName = "cute";
tclAppLongName = "Call Unix/Tcl Environment";
tclAppVersion = "2.1";
Note that the default values are set by TclX_Init, so if you
wish to override them, you must call your init routine in
Tcl_AppInit after its call to TclX_Init.
EXTENDED TCL EXIT
When Extended Tcl exits, Tcl_DeleteInterp may be called to
free memory used by Tcl -- normally, this is only called if
TCL_MEM_DEBUG was defined, since Unix will return all of the
allocated memory back to the system, anyway. If
TCL_MEM_DEBUG was defined, it is called so that any memory
that was allocated without ever being freed can be detected.
This greatly reduces the amount of work to detect and track
down memory leaks, a situation where some piece of your code
allocates memory repeatedly without ever freeing it, or
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 Berkeley Tcl.
EXECUTING TCL CODE FROM YOUR C
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 the Tcl_Eval, Tcl_VarEval,
Tcl_EvalFile and Tcl_GlobalEval functions for the purpose of
executing Tcl code from within a C extension. The results
of the call will be in interp->result. For more information
please consult the Eval(3) manual page within the Berkely
Tcl distribution.
ACCESSING TCL VARIABLES AND ARRAYS FROM
Tcl variables and arrays can be read from a C extension
through the Tcl_GetVar and Tcl_GetVar2 functions, and set
from C extensions through the Tcl_SetVar and Tcl_SetVar2
functions. They can also be unset via the Tcl_UnsetVar and
Tcl_UnsetVar2 functions. For complete information on these
functions, please refer to the SetVar(3) manual page in the
doc directory of the Berkeley 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 will be 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.
Whenever the Tcl variable is read the value of the C
variable will be returned, and whenever the Tcl variable is
written the C variable will be updated to have the same
value.
Int, double, boolean and char * variables are supported.
For more information, please examine the LinkVar(3) manual
page in the Berkeley 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
calls for these functions for many releases.
New math functions can be added to Tcl, or existing math
functions can be replaced, by calling Tcl_CreateMathFunc.
For more information on adding math functions, please
examine the CrtMathFnc(3) manual page in the Berkeley Tcl
distribution.
PERFORMING TILDE SUBSTITUTIONS ON FILENAMES
The Tcl_TildeSubst function is available to C extension
writers to perform tilde substitutions on filenames. 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 TildeSubst(3) manual page in the Berkeley Tcl
distribution.
SETTING THE RECURSION LIMIT
Tcl has a preset recursion limit that limits the maximum
allowable nesting depth of calls within an interpreter.
This is useful for detecting infinite recursions before
other limits such as the process memory limit or, worse,
available swap space on the system, are exceeded.
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 Berkeley Tcl distribution.
HANDLING SIGNALS FROM TCL EXTENSIONS
If an event such as a signal occurs while a Tcl script is
being executed, it isn't safe to do much in the signal
handling routine -- the Tcl environment cannot be safely
manipulated at this point because it could be in the middle
of some operation, such as updating pointers, leaving the
interpreter in an unreliable state.
The only safe approach is to set a flag indicating that the
event occurred, then handle the event later when the
interpreter has returned to a safe state, such as after the
current Tcl command completes.
The Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, and
Tcl_AsyncDelete functions provide a safe mechanism for
dealing with signals and other asynchronous events. For
more information on how to use this capability, please refer
to the Async(3) manual page in the Berkeley Tcl
distribution.
PARSING BACKSLASH SEQUENCES
The Tcl_Backslash function is called to parse Tcl backslash
sequences. These backslash sequences are the usual sort
that you see in the C programming language, such as \n for
newline, \r for return, and so forth. Tcl_Backslash parses
a single backslash sequence and returns a single character
corresponding to the backslash sequence.
For more info on this call, look at the Backslash(3) manual
page in the Berkeley Tcl distribution. For information on
the valid backslash sequences, consult the summary of Tcl
language syntax, Tcl(n) in the same distribution.
HASH TABLES
Hash tables provide Tcl with a high-performance facility for
looking up and managing key-value pairs located and
maintained in memory. Tcl uses hash tables internally to
locate procedure definitions, Tcl variables, array elements,
file handles and so forth. Tcl makes the hash table
functions accessible to C extension writers as well.
Hash tables grow automatically to maintain efficiency,
rather than exposing the table size to the programmer at
allocation time, which would needlessy 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 life of the program.
For more information on hash tables, please consult the
Hash(3) manual page in the Berkeley Tcl distribution.
TRACING VARIABLE ACCESSES
The C extension writer can arrange to have a C routine
called whenever a Tcl variable is read, written, or unset.
Variable traces are the mechanism by which Tk toolkit
widgets such as radio and checkbuttons, messages and so
forth update without Tcl programmer intervention when their
data variables are changed. They are also used by the
routine that links Tcl and C variables, Tcl_LinkVar,
described above.
Tcl_TraceVar is called to establish a variable trace.
Entire arrays and individual array elements can be traced as
well. If the programmer already has an array name in one
string and a variable name in another, Tcl_TraceVar2 can be
called. Calls are also available to request information
about traces and to delete them.
For more information on variable traces, consult the
TraceVar(3) manual page in the Berkeley Tcl distribution.
TRACING EXECUTION
Tcl has the ability to call C routines for every command it
executes, up to a specified depth of nesting levels. The
command Tcl_CreateTrace creates an execution trace;
Tcl_DeleteTrace deletes it.
Command tracing is used in Extended Tcl to implement the
cmdtrace Tcl command, a useful command for debugging Tcl
applications.
For complete information on execution tracing, please look
at the CrtTrace(3) manual pages in the Berkeley Tcl
distribution.
EVALUATING TCL EXPRESSIONS FROM C
Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBool, and
Tcl_ExprString can be called to evaluate Tcl expressions
from within a C routine. 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 * (pointed to by interp-
>result).
For complete information on evaluating Tcl expressions from
C, you are invited to examine the ExprLong(3) manpage in the
Berkeley 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 Berkeley 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.
For more information on this function, please consult the
RegExp(3) manpage in the Berkeley Tcl distribution.
MANIPULATING TCL LISTS FROM C EXTENSIONS
The C extension writer often needs to create, manipulate and
decompose Tcl lists. Tcl_SplitList parses a list into an
argv and argc like to the way command-line arguments are
passed to a Tcl extension. Tcl_Merge, likewise, creates a
single string (pointer to a char *) from an argv and argc.
Two routines, Tcl_ScanElement and Tcl_ConvertElement, do
most of the work of Tcl_Merge, and may also be of use to the
C programmer.
For more information on these commands, please consult the
SplitList(3) manual page in the Berkeley Tcl distribution.
CONCATENATING STRINGS
Tcl_Concat concatenates zero or more strings into a single
string. The strings are space-separated. Tcl_Concat works
like Tcl_Merge, except that Tcl_Concat does not attempt to
make the resulting string into a valid Tcl list.
Tcl_Concat is documented in the Concat(3) manpage in the
Berkeley Tcl distribution.
DETECTING WHETHER OR NOT YOU HAVE
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.) Tcl_CommandComplete can be used to
tell whether or not you have a complete command.
For more information examine CmdCmplt(3) in the Berkeley Tcl
distribution.
RECORDING COMMANDS FOR COMMAND HISTORY
Tcl has a history mechanism that is accessed from Tcl
through the history command. To propagate commands into the
command history, your extension should call
Tcl_RecordAndEval. This command works just like Tcl_Eval,
except that it records the command as well as executing it.
Tcl_RecordAndEval 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 this function, please examine
the RecordEval.3 manual page in the Berkeley Tcl
distribution.
CONVERTING FLOATING POINT VALUES TO STRINGS
Tcl_PrintDouble converts a C double into an ASCII string.
It ensures that the string output will continue to be
interpreted 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 Tcl_PrintDouble, examine
PrintDbl(3) in the Berkeley Tcl distribution.
CREATING CHILD PROCESSES AND PIPELINES FROM
Tcl_CreatePipeline is a useful procedure for spawning child
processes. 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_CreatePipeline, please examine CrtPipelin(3).
ACCESSING TCL FILEHANDLES FROM C
Files opened from your C code can be made visible to Tcl
code via the Tcl_EnterFile function. Likewise, Tcl
filehandles passed to your C extension can be translated to
a Posix FILE * structure using the Tcl_GetOpenFile function.
For complete explanations of these commands, please look at
EnterFile(3) in the Berkeley Tcl distribution.
MANAGING BACKGROUND PROCESS TERMINATION AND CLEANUP
When a Posix system does a fork to create a new process, the
process ID of the child is returned to the caller. After
the child process exits, its process table entry (and some
other data associated with the process) cannot be reclaimed
by the operating system until a call to waitpid, or one of a
couple of other, similar system calls, has been made by the
parent process.
The C extension writer who has created a subprocess, by
whatever mechanism, can turn over responsibility for
detecting the processes' termination and calling waitpid to
obtain its exit status by calling Tcl_DetachPids.
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.
For complete information on these routines, please look at
DetachPids(3) in the Berkeley 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. The comp.lang.tcl Usenet
newsgroup is read by tens of thousands of Tcl people, and is
a good place to ask questions. Finally, if you have
interactive Internet access, you can ftp to
ftp.aud.alcatel.com, the site for contributed Tcl sources.
This site contains quite a few extensions, applications, and
so forth, including several object-oriented extension
packages.