ftp.nice.ch/pub/next/developer/objc/appkit/TclExample.README

This is the README for TclExample.1.0.s.tar.gz [Download] [Browse] [Up]

TclObj - An Interface Between Objective-C and Tcl

This package contains a simple class called TclObj whose purpose is
to provide a salubrious interface between Objective-C and Tcl. Tcl is
a small interactive C-Shell like language developed at UC Berkeley. You
can obtain tcl from the UUNET archives.

The main use of this class, as I see it, is to provide a programmable
layer between a user interface built with Interface Builder and
the 'guts' of an application.

There are four components to this package:

TclObj.{hm} - This is the implementation of the tcl interface class.
TclApp.{hm} - This implements the tcl to application interface.
TclTV.{hm} - This is a small text editor object for use in debugging tcl progs.
TclIF.m - Procedure mappings between Tcl and 'C'.

To hook tcl into a user interface with IB do the following:

1) An instance of TclObj should be created in the main .nib file for an 
application.

2) A segment called "TCL" with a section called "init" should be created in
the program executable. The data in this segment/section should be the ascii
text of the commands that you want to be executed when the TclObj is created.
In the example I have a very simple set of start up commands that basically
"source" in an external text file with the "real" start up stuff. If you 
wanted to have an application that doesn't have any external files hanging
around you would put all your initializations into the "init" section.
Note that TclObj initializes several useful global variables in the tcl
interpreter that it creates. 'NXApp' is the ascii representation of the
id for NXApp. 'TclObj' is the ascii rep for the TclObj instance id. These
globals are initialized before the "init" section is evaluated. 

5) Hook action messages from controls in the user interface to the 'msg' action
in the TclObj. Each message that arrives will be converted to a tcl call
to the procedure 'msg' with one argument which is the ascii representation of
the senders id. At present this is the only interface from Objective-C into
tcl.

7) If you want to invoke commands in the tcl interpreter from "outside" you can 
send the TclObj object a 'doCmd' message with the first argument being the
string containing the tcl command and the second argument being NULL.

At this point you should have a Tcl interface object linked into your
user interface.

The next problem is to control the user interface and the application from
Tcl. In order to do this you need some way to call 'C' routines from Tcl.

You could write a small Tcl to C converter routine for each C routine that
you want to call but this would end up being a lot of procedures with much
in common.

In order to get around this I have implemented a routine called "tclCall".
This routine takes a pointer to a 'C' procedure and a string containing
a description of the procedure arguments (similar to the typed stream stuff).

See the comments in TclApp.m for details on the use of tclCall.

Part of the initialization of a TclObj is to define a bunch of procedures
for the Tcl interpreter such that they call "tclCall" and pass along the
required argument conversions. The list of definitions is defined in
TclIF.m.

In order to get Tcl access to more procedures from the NeXT library you would
add lines to the list in TclIF.m. You would also add lines in this file
to link in your application procedures.

The interface from Tcl to Objective-C messages uses the above code. The
Tcl "send" procedure is defined in TclIF.m to call "objc_msgSend". The
argument description for this routine is an empty string which indicates
that the actual argument string is passed in as the first argument to "send".
This way you can form a wide variety of messages directly from Tcl without
having to play with the low level C code.

Debugging Tcl Procedures.

I have provided a small class which implements a text editor / command input
function for the TclObj class. You can create one or more tcl edit windows
by invoking the 'createTextView:' message in the TclObj.

If you have an edit window on the screen you may type tcl commands into it
and execute them. The edit window acts like a standard NeXT text object
except that I have intercepted the enter character to cause command invocation.
The way this works is as follows. At the time you hit enter the code 
checks the current selection. If the selection is just an insertion point
but has no width then the line that the insertion bar is on is evaluated
by tcl and the results are added to the bottom of the edit text. If the
selection has a width then the selection is evaluated by tcl and the
result is added to the bottom of the edit window.

The first edit window will display the result of commands invoked by the
'msg' message. Other edit windows will only echo results of commands typed
into them. All edit windows share the same tcl interpreter. If you don't
bring up an edit window then tcl output is ignored. In this case you could
use the tcl 'print' command to write stuff on stdout if you invoked the
application from a shell.

Future Features.

This code is a very machine dependent HACK but it does seem to work! Of
course you could go a L...O...T further. You could get rid of the need to
explicitly define the argument types for messages by using the new
procedures provided for dealing with the "forward" and "performv" methods.
You could allow dynamic addition of methods to the TclObj class. You could
use symbol table information to dynamically call C routines. All of this
comes under the heading of a "correct and complete" interface between
Tcl and C/Objective-C. If you get time to add any of these (or any other)
features I would be interested in having a look.

WARNING STUDENT DRIVER. I wrote this class as my first NeXT project so beware!

Enjoy,

Grant Munsey, Manticore, Inc, grant@gouche.portal.com, (408)733-3838

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.