sgitcl(1)
sgitcl - Tcl shell for SGI
As shipped in IRIX 6.5. First release of IRIX 6.5.
NAME sgitcl - Tcl shell for SGI INTRODUCTION This man page describes the Tcl shell for SGI. This shell includes Tcl and TclX, and a shared library command which allows a single executable program to include any mix of extension libraries. The extension libraries are built as shared objects. For example, the Tcl distribution includes an extension library for tclMotif (or Tm), the Tcl binding to the Motif widget toolkit. For a summary of the Tcl language, see the Tcl(3) man page. For a summary of the extensions added by TclX, see the TclX(3) man page. For an overview of tclMotif, see the tclMotif(3) man page. The remainder of this man page describes the dlopen command, used to open and initialize extension libraries; and describes how to build an existing extension package as a shared library. Building a shared library Build the .so using the -shared option to ld or cc. Make sure that the build line references all libraries that are needed by the extension library; for example, Tk requires "-lX11 -lc -lm". Adding the -no_unresolved flag will ensure that there are no unresolvable symbols which will probably save you time later. Many of the TCL packages come with a makefile that builds a .a archive which can be given to ld to build the shared object. If not, you'll need to identify what object files need to be included in the build; for extensions that follow the conventions, this usually means everything except the file containing the Tcl_AppInit routine, since your library will be initialized by a TCL command. If you are developing your own library, you will have to define an initialization routine that adds your new Tcl commands to the interpreter (using Tcl_CreateCommand) and performs any other necessary initialization. By convention this routine is named "<module_name>_Init" where <module_name> is a short acronym for your extension library (e.g. Tk_Init, Tm_Init, TclX_Init). This routine takes a Tcl_Interp pointer as its only argument. Build the shared object as described above. Install the .so in /usr/lib or /usr/sgitcl/lib. Now you are ready to try opening the library. Opening a shared library The dlopen command opens a dynamic shared object (using the dlopen system call). An init or call (see below) may optionally be appended to the end of the command. The first argument must be the name of the library to open. The library name is passed directly to dlopen, which looks for it in /usr/lib and /usr/sgitcl/lib (this was added to the sgitcl executable at link time). If your LD_LIBRARY_PATH environment symbol is set, that will also be searched. An absolute pathname may also be specified; see the dlopen(3) man page for more information on the library path name. The mode parameter is hard-coded to RLTD_LAZY. After the library is opened successfully, a new TCL command will be added with the same name as the library file; this command can be used to call subroutines in the library by name, using the dlsym(3) system call to resolve the symbol name. Two function prototypes are provided: the init prototype and the call prototype. The prototypes are defined below: void init_routine(Tcl_Interp* interp); int call_routine(void *data, Tcl_Interp* interp, int argc, char* argv[]); The init prototype is specifically designed to call the initialization routine for an extension package that would normally be called from the Tcl_AppInit routine. For example, the following line will open and initialize the tclMotif library (assuming it has been linked as a dynamic shared object): dlopen libtclMotif.so init Tm_Init This line will open the library libtclMotif.so, and then call the routine Tm_Init, passing the Tcl_Interp pointer as its only argument. The call prototype allows an arbitrary parameter list to be passed to the routine, as an argc, argv vector, much like the interface to a Tcl command. Any values specified after the routine name will be passed as strings to the routine. For Example, the command: dlopen mylib.so call myroutine one two three Will open the library "mylib.so" and then call the routine named "myroutine", passing a NULL for "data", the Tcl_Interp argument, the value 3 for the argc parameter, and three strings: "one", "two", and "three" in the argv array. A call_routine should return TCL_OK if successful, or TCL_ERROR (with an appropriate error message deposited in interp->result) on failure. The return value of the dlopen command will be the value of interp- >result, which can be set by the init or call routine to a meaningful value; the default return value is an empty string. Suppose we build a library called libmine.so which has an init routine: int My_Init(Tcl_Interp* interp) { strcpy(interp->result, "My_Init"); return TCL_OK; } and another routine: int My_Command(ClientData data, Tcl_Interp* interp, int argc, char* argv[]) { /* some interesting code */ strcpy(interp->result, "Finished My_Command"); return TCL_OK; } (if you are programming in C++, be sure to specify these as 'extern "C"' routines to avoid name mangling). We have built the library libmine.so and put it in /usr/lib. Now we type: % sgitcl sgitcl>dlopen libmine.so init My_Init My_Init The init routine ran and sgitcl printed the returned value "My_Init" Now we type: % sgitcl sgitcl> dlopen libmine.so sgitcl> libmine.so init My_Init My_Init protcl> libmine.so call My_Command "this is a test" second $var Finished My_Command The call to My_Command will be passed: argc set to 3 (three) argv[0] set to "this is a test" argv[1] set to "second" argv[2] set to the value of the TCL variable "var" argv[3] will be NULL (zero). Trouble shooting If the dlopen command returns an error: First make sure you put the .so in /usr/lib or /usr/sgitcl/lib. If so, then you probably have unresolvable symbols in your library; the best way to avoid this is to specify -no_unresolved when you link the shared object. Re-link the shared object and make sure there are no unresolved symbols. If this doesn't work, refer to the documentation on the dlopen system call. If dlopen returns "no such routine <init-routine>": The init routine you specified is not defined in the library. Make sure the routine was included in the object list. Some packages may fold this routine into the same file with Tcl_AppInit; in this case you will need to edit this file to remove Tcl_AppInit (comment it out or use #ifdef's), add the file to the link list and re-build the library. Startup Files Before any evaluation occures a system wide startup file named system.<interp-name>rc is executed. A good way to automatically load in a library of routines for a class of scripts is to create a link to sgitcl with a new name and to create a system.namerc script in the Tcl library directory, which will dlopen the appropriate library and do any specific startup needed. Example: expect is a symbolic link to /usr/sgitcl/bin/sgitcl /usr/sgitcl/lib/system.expectrc contains: dlopen libexpect.so init Exp_Init eval exp_run [split $argv] On interactive runs a per-user startup script ~/.<interp-name>rc is also sourced just before dropping into the commandloop. This script can be used by individuals to setup commonly used proceedures or to override default behavior. FILES /usr/sgitcl/lib/system.sgitcl system wide startup script $HOME/.sgitcl user startup script