home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / Tickle-4.0 (tcl) / tcl / extend / man / CmdWrite.3 next >
Encoding:
Text File  |  1993-10-26  |  13.3 KB  |  318 lines  |  [TEXT/MPS ]

  1. .\"
  2. .\" CmdWrite.man
  3. .\"
  4. .\" Command writing manual.
  5. .\"----------------------------------------------------------------------------
  6. .\" Copyright 1992-1993 Karl Lehenbauer and Mark Diekhans.
  7. .\"
  8. .\" Permission to use, copy, modify, and distribute this software and its
  9. .\" documentation for any purpose and without fee is hereby granted, provided
  10. .\" that the above copyright notice appear in all copies.  Karl Lehenbauer and
  11. .\" Mark Diekhans make no representations about the suitability of this
  12. .\" software for any purpose.  It is provided "as is" without express or
  13. .\" implied warranty.
  14. .\"----------------------------------------------------------------------------
  15. .\" $Id: CmdWrite.3,v 2.1 1993/07/20 08:35:45 markd Exp $
  16. .\"----------------------------------------------------------------------------
  17. .\"
  18. .TH "Command Writing" TCL "" "Tcl"
  19. .ad b
  20. .SH NAME
  21. TclCommandWriting - Writing C language extensions to Tcl.
  22. '
  23. .SH OVERVIEW
  24. This document is intended to help the programmer who wishes to extend
  25. Tcl with C language routines.  It should also be useful to someone
  26. wishing to add Tcl to an existing editor, comm program, etc.  There
  27. is also programming information in the \fITcl.man\fR manual
  28. directory of the Berkeley distribution.
  29. '
  30. .SH WRITING TCL EXTENSIONS IN C
  31. C extensions to Tcl must be written to receive their arguments in the
  32. manner Tcl uses to pass them.
  33. .PP
  34. A C routine is called from Tcl with four arguments, a client data pointer,
  35. an interpreter pointer, an argument count and a pointer to an array of
  36. pointers to character strings containing the Tcl arguments to the routine.
  37. .PP
  38. A Tcl extension in C is now presented, and described below:
  39. .sp
  40. .nf
  41. .ft CW
  42.     #include "tcl.h"
  43.  
  44.     int Tcl_EchoCmd(clientData, interp, argc, argv)
  45.         void       *clientData;
  46.         Tcl_Interp *interp;
  47.         int         argc;
  48.         char      **argv;
  49.     {
  50.             int i;
  51.  
  52.             for (i = 1; i < argc; i++) {
  53.                     printf("%s ",argv[i]);
  54.             }
  55.             printf("\\n");
  56.             return TCL_OK;
  57.     }
  58. .ft R
  59. .fi
  60. .PP      
  61. The client data pointer will be described later.
  62. .PP
  63. The interpreter pointer is the ``key'' to an interpreter.  It is returned by
  64. \fITcl_CreateInterp\fR or \fITcl_CreateExtendedInterp\fR and is used within
  65. Tcl and by your C code.  The structure pointed to by the interpreter pointer,
  66. and all of the subordinate structures that branch off of it, make up an
  67. interpreter context, which includes all of the currently defined procedures,
  68. commands, variables, arrays and the execution state of that interpreter.
  69. .PP
  70. The argument count and pointer to an array of pointers to textual arguments
  71. is handled by your C code in the same manner that you would use in writing a
  72. C \fImain\fR function -- the argument count and array of pointers
  73. works the same
  74. as in a C \fImain\fR call; pointers to the arguments to the function are
  75. contained
  76. in the \fIargv\fR array.  Similar to a C main, the first argument
  77. (\fIargv[0]\fR) is the
  78. name the routine was called as (in a main, the name the program
  79. was invoked as).
  80. .PP
  81. In the above example, all of the arguments are output with a space between
  82. each one by looping through \fIargv\fR from one to the argument count,
  83. \fIargc\fR, and a
  84. newline terminates the line -- an echo command, although a ``real'' echo
  85. command would not add a trailing blank like this one does.
  86. .PP
  87. All arguments from a Tcl call to a Tcl C extension are passed as strings.
  88. If your C routine expects certain numeric arguments, your routine must first
  89. convert them using the \fITcl_GetInt\fR or \fITcl_GetDouble\fR
  90. function, or some other method
  91. of your own devising.  If you program produces a numeric result, it should
  92. return a string equivalent to that numeric value.  A common way of doing
  93. this is something like...
  94. .sp
  95. .nf
  96. .ft CW
  97.     sprintf(interp->result, "%ld", result);
  98. .ft R
  99. .fi
  100. .PP      
  101. More sophisticated commands should verify their arguments when possible,
  102. both by examining the argument count, by verifying that numeric fields
  103. are really numeric, that values
  104. are in range when their ranges are known, and so forth.
  105. .PP
  106. Tcl is designed to be as bullet-proof as possible, in the
  107. sense that Tcl programs should not be able to cause Tcl to dump core.  Please
  108. do the same with your C extensions by validating arguments as above.
  109. .PP
  110. In the command below, two or more arguments are compared and the one with
  111. the maximum value is returned, if all goes well.  It is an error if there
  112. are fewer than three arguments (the pointer to the ``max'' command text itself,
  113. \fIargv[0]\fR, and pointers to at least two arguments to compare the
  114. values of).
  115. .PP
  116. This routine also shows the use of the programmer labor-saving
  117. \fITcl_AppendResult\fR
  118. routine.  See the Tcl manual page, \fISetResult.man\fR, for details.
  119. Also examine the calls \fITcl_SetErrorCode\fR and \fITcl_UnixError\fR
  120. documented in the Tcl manual page \fIAddErrInfo.man\fR.
  121. .sp
  122. .nf
  123. .ft CW
  124.     int
  125.     Tcl_MaxCmd (clientData, interp, argc, argv)
  126.         char       *clientData;
  127.         Tcl_Interp *interp;
  128.         int         argc;
  129.         char      **argv;
  130.     {
  131.         int maxVal = MININT;
  132.         int maxIdx = 1;
  133.         int value, idx;
  134.  
  135.  
  136.         if (argc < 3) {
  137.             Tcl_AppendResult (interp, "bad # arg: ", argv[0],
  138.                               " num1 num2 [..numN]", (char *)NULL);
  139.             return TCL_ERROR;
  140.         }
  141.  
  142.         for (idx = 1; idx < argc; idx++) {
  143.             if (Tcl_GetInt (argv[idx], 10, &Value) != TCL_OK)
  144.                 return TCL_ERROR;
  145.  
  146.             if (value > maxVal) {
  147.                 maxVal = value;
  148.                 maxIdx = idx;
  149.             }
  150.         }
  151.         strcpy (interp->result, argv [maxIdx]);
  152.         return TCL_OK;
  153.     }
  154. .ft R
  155. .fi
  156. .PP      
  157. When Tcl-callable functions complete, they should normally return
  158. \fBTCL_OK\fR or \fBTCL_ERROR\fR.
  159. \fBTCL_OK\fR is returned when the command succeeded and \fBTCL_ERROR\fR
  160. is returned when the command has failed rather drastically.  
  161. \fBTCL_ERROR\fR should
  162. be returned for all syntax errors, non-numeric values where numeric ones
  163. were expected, and so forth.  Less clear in some cases is whether Tcl errors
  164. should be returned or whether a function should just return a status value.
  165. For example, end-of-file during a \fIgets\fR returns a status,
  166. but \fIopen\fR
  167. returns an error if the open fails.  Errors can be caught from
  168. Tcl programs using the \fIcatch\fR command.
  169. .PP
  170. Less common return values are 
  171. \fBTCL_RETURN\fR, \fBTCL_BREAK\fR and \fBTCL_CONTINUE\fR.
  172. These are used if you are adding new control and/or looping
  173. structures to Tcl.  To see these values in action, examine the source to
  174. the \fIwhile\fR, \fIfor\fR, \fIif\fR and \fIloop\fR commands.
  175. '
  176. .SH INSTALLING YOUR COMMAND
  177. .P
  178. To install your command into Tcl your must call 
  179. \fITcl_CreateCommand\fR, passing
  180. it the pointer into the interpreter you want to install the command into,
  181. the name of the command, a pointer to the C function, a client data pointer,
  182. and a pointer to an optional callback routine.
  183. .PP
  184. The client data pointer and the callback routine will be described later.
  185. .PP
  186. For example, for the max function above (which incidentally comes from
  187. math.c in the extend/src directory):
  188. .sp
  189. .nf
  190. .ft CW
  191.     Tcl_CreateCommand (interp, "max", Tcl_MaxCmd, (ClientData)NULL, 
  192.                       (void (*)())NULL);
  193. .ft R
  194. .fi
  195. .PP
  196. In the above example, the max function is added
  197. to the specified interpreter.  The client data pointer and callback
  198. function pointer are NULL.
  199. .PP
  200. .SH CLIENT DATA
  201. .PP
  202. The client data pointer provides a means for Tcl commands to have data
  203. associated through them that is not global to the C program including
  204. the Tcl core.  It is essential in a multi-interpreter environment
  205. (where a single program has created and is making use of multiple
  206. Tcl interpreters)
  207. for the C routines to maintain any permanent data they need relative to
  208. each interpreter being used, or there would be reentrancy problems.
  209. Tcl solves this through the client data mechanism.  When you are about
  210. to call 
  211. \fITcl_CreateCommand\fR to add a new command to an interpreter, if that
  212. command needs to keep some read/write data from one invocation to another,
  213. you should allocate the space, preferably using \fIckalloc\fR, then pass
  214. the address of that space as the ClientData pointer to
  215. \fITcl_CreateCommand\fR.
  216. .PP
  217. When your command is called from Tcl, the ClientData pointer you gave to 
  218. \fITcl_CreateCommand\fR when you added the command to that interpreter
  219. is passed
  220. to your C routine through the ClientData pointer calling argument.
  221. .PP
  222. Commands that need to share this data with one another can do so by using the
  223. same ClientData pointer when the commands are added.
  224. .PP
  225. It is important to note that the Tcl extensions in the extended/src
  226. directory have had all of their data set up in this way, so at
  227. the time of this writing (release 6.2) the Tcl extensions support
  228. multiple interpreters within one invocation of Tcl.
  229. '
  230. .SH INTEL '286 GOTCHAS
  231. .P
  232. The '286 programmer who is not using an ANSI C standard compiler with
  233. function prototypes must be vigilant to ensure that anytime NULL is
  234. passed to a function as a pointer it is explicitly cast to
  235. \fB(void *)\fR or equivalent.  Also remember that Tcl math within
  236. expressions is carried out to 32 bits, so that you should usually use
  237. the \fIlong\fR variable type for your integers, \fITcl_GetLong\fR (rather
  238. than \fITcl_GetInt\fR) to convert strings to long integers, and remember
  239. to use \fB%ld\fR when printing results with \fIsprintf\fR, and so
  240. forth.
  241. .PP
  242. To maintain '286 compatibility, all C programmers are asked to follow
  243. these guidelines.  I know you don't want to, but there are a lot of
  244. 286 machines out there and it is nice that they are able to run Tcl.
  245. .SH THEORY OF HANDLES
  246. Sometimes you need to have a data element that isn't readily representable
  247. as a string within Tcl, for example a pointer to a complex C data structure.
  248. We do not think it is a good idea to try to pass pointers around within
  249. Tcl as strings by converting them to and from hex or integer representations,
  250. for example.  It is too easy to screw one up and the likely outcome of
  251. doing that is a core dump.
  252. .PP
  253. Instead what we have done is developed and made use of the concept 
  254. of \fIhandles\fR.
  255. Handles are identifiers a C extension can pass to, and accept from,
  256. Tcl to make the transition between what your C code knows something as
  257. and what name Tcl knows it by to be as safe and painless as possible.  
  258. For example,
  259. the stdio package included in Tcl uses file handles.  When you open a
  260. file from Tcl, a handle is returned of the form \fBfile\fIn\fR where
  261. \fIn\fR is a file number.  When you pass the file handle back to \fIputs\fR,
  262. \fIgets\fR, \fIseek\fR, \fIflush\fR and so forth, they validate the file
  263. handle by checking the the \fBfile\fR text is present, then converting
  264. the file number to an integer that they use to look into a data
  265. structure of pointers
  266. to Tcl open file structures, which contain a Unix file descriptor, flags
  267. indicating whether or not the file is currently open, whether the file is
  268. a file or a pipe and so forth.
  269. .PP
  270. Handles have proven so useful that, as of release 6.1a, general support
  271. has been added for them.
  272. If you need a similar capability, it would be best to use the handle
  273. routines, documented in \fIHandles.man\fR.
  274. We recommend that you use a
  275. unique-to-your-package textual handle coupled with a specific identifier
  276. and let the handle management routines validate it when it's passed back.
  277. It is much easier to
  278. track down a bug with an implicated handle named something like \fBfile4\fR
  279. or \fBbitmap6\fR than just \fB6\fR.
  280. .PP
  281. .SH TRACKING MEMORY CORRUPTION PROBLEMS
  282. Occasionally you may write code that scribbles past the end of an
  283. allocated piece of memory.  The memory debugging
  284. routines included in Tcl can help find these problems.  See
  285. \fIMemory(TCL)\fR for details.
  286. .PP
  287. .SH WRITING AN APPLICATION-SPECIFIC MAIN
  288. For those writing an application-specific main, for example, those adding
  289. Tcl to an existing application or including Tcl within a larger application,
  290. a few steps need to be taken to set up Tcl.
  291. .PP
  292. For one thing, several \fIextern char *\fR definitions must be fulfilled,
  293. providing data used by the \fIinfox\fR command.  These definitions are
  294. \fItclxVersion\fR, the Extended Tcl version number, \fItclxPatchlevel\fR,
  295. the Extended Tcl patch level, \fItclAppName\fR, the name of the application,
  296. \fItclAppLongname\fR, a description of the application, and
  297. \fItclAppVersion\fR, the version number of the application.
  298. .PP
  299. A Tcl interpreter, including all of the extensions in Extended Tcl, is
  300. created with a call to \fITcl_CreateExtendedInterp\fR.  Next, any
  301. application-specific commands are added by calls to \fITcl_CreateCommand\fR.
  302. Finally, \fITcl_Startup\fR is called to load the Tcl startup code, pull
  303. in all of the Tcl procs and paths, do command line processing, handle
  304. autoloads, packages, and so forth.  If the application writer wants
  305. different startup behavior, they should write a different Tcl startup
  306. routine.  \fITcl_Startup\fR is defined in the file \fItclstartup.c\fR
  307. in the \fIextended/src\fR directory.
  308. .PP
  309. Finally, cleanup code is called to close down the application.
  310. \fITcl_DeleteInterp\fR is called to free memory used by Tcl -- normally,
  311. this is only called if \fBTCL_MEM_DEBUG\fR was defined, since Unix
  312. will return all of the allocated memory back to the system, anyway.
  313. .PP
  314. The writer of an application-specific main is invited to examine and use
  315. the \fImain()\fR routine defined in \fIextended/src/main.c\fR
  316. as a template for their new main.  There is a \fItcl++.C\fR, which is a
  317. main for C++-based Tcl applications.
  318.