---- Shells 1.0 -------------------------------------------------------------- This package implements multiple extensions management and dynamic linking for Tcl/Tk as suggested in "Tcl Future Directions Session #2 Notes" (as posted to comp.lang.tcl; see session2.txt for details). It includes a basic Tcl shell (tcl.c), a modified wish shell (tk.c) and a dynamic extension loader for SunOs (dl.c, sun.c). I've tried to adhere as closely as possible to the suggested solutions, but in a few occasions interpolation was required: * the notes don't explicitly define the return type for Tcl_AppInit() and for the extension-specific initialization functions. I've decide to have them return TCL_OK or TCL_ERROR to report success or failure. * widgets factories for Tk need to know the data structure of the application main window, declared as static in main.c: I've introduced a new function (Tk_Window Tk_MainWindow(void)) to get it from within extensions. * a policy about application and extension initialization scripts is still to be defined: it's up to you choosing between: 1. organizing your code as suggested by J.O. in the book: - compile a standard path for the script library in the sources and allow the user to modify it using an environment variable (LIB) - in _Init() look for the init file in LIB and in the hard-coded path and then call Tcl_FileEval() to source it. 2. using autoloading - define in the script library an initialization Tcl procedures (_Init) - include the directory containing the script library in auto_path/TCLLIBPATH - in _Init() call Tcl_GlobalEval(interp, " ...]") and let the standard auto-loader find the proper file to source. tcl.c and tk.c are aware of Tcl_AppInit() and invoke it to perform application-specific initialization before executing required actions. To build applications based on extended shells: * compile either tcl.c or tk.c passing -DEXTENDED as option to the C compiler. * link the object with extension libraries and an application-specific module exporting "int Tcl_AppInit(Tcl_Interp *)". This function should call the initialization function of each required extension, perform application-specific initialization and then return TCL_OK or TCL_ERROR to report success or failure. ---- Dynamic Loading ---------------------------------------------------------- The dynamic extension module (sun.c) take advantage of dynamic loading of shared libraries under SunOs to load extensions in tcl/tk shells at run-time. Use the included Makefile to build and install dynamically extensible shells for tcl (dtcl) and tk (dwish) and related manual pages. The code provides a general-purpose Tcl_AppInit() function that creates a new Tcl command (load), checks the proper installation of standard Tcl auto-loading procedures and stores in a Tcl variable (dl_version) the current version tag of the package. Extensions to be loaded at run-time should be compiled as shared libraries and should define a public initialization function taking as argument a pointer to the Tcl interpreter to be extended and returning TCL_OK or TCL_ERROR to report success or failure. Extension complying with these rules can be loaded using the 'load' Tcl command: it takes as arguments the path of the shared library to load and the name of the initialization function to call. Dynamic loading can be hacked quite effectively in the standard auto-loading scheme: in this way it should be possible to load multiple libraries without much trouble. In the demo directory you'll find an example of compiling and installing a shared auto-loadable library under SunOs: it includes a fact(orial) command and the sample Tk square widget. ---- To Install --------------------------------------------------------------- To build dynamic shells on SunOs and try out dynamic loading: * build dwish using the Makefile in the current directory * cd to demo/ * edit the Makefile and build libdemo (have a look into libdemo.tcl and at the man page for the load command to see how auto-loading works). * run ../dwish * build the auto-loading index and insert it in the auto-loading path with the following command: wish: auto_mkindex . *.tcl wish: lappend auto_path . * enjoy (hopefully :-)): wish: fact 5 wish: source square.tcl ---- Porting ------------------------------------------------------------------ Even if it's based on Sun-specific functions, it shouldn't be difficult to port sun.c to different architectures, provided they support dynamic loading at the system level. In order to do that you need to replace dlopen() (to load a library), dlsym() (to fetch a pointer to a given symbol) and dlerror() to find out what went wrong after an error in dlopen() or dlsym(). GNU's dld and the dynamic loading support for the Class language in the Andrew ToolKit may provide useful ideas to start with. I'm willing to maintain the package (no hot-line support :-)), so if you succeed in porting the load command to other systems please send me patches and relevant documentation. To ease configuration and maintenance I suggest you should try to confine system-dependent stuff in a file $YourArchitecture.c, defining a single interface function: int dl_load(Tcl_Interp *interp, char *path, char *initFun) It takes as arguments the pointer to the Tcl interpreter to be extended, the path of the library to load and the name of the initialization function to use. It should return TCL_OK or TCL_ERROR, leaving an error message in interp->result in the latter case. ------------------------------------------------------------------------------ Comments and suggestions to: ------------------------------------------------------------------------------ Alessandro Bollini --- bollini@ipvvis.unipv.it Dipartimento di Informatica e Sistemistica - Universita` di Pavia - Italia