Re: how does Tcl/Tk work?



Till wrote:

>
I was trying to understand how TKEMC connects to the EMC and I expected the
tcl/tk code to show how this works. I thought there would have to be the command
"socket" somewhere in order to connect to the emcserver. But I didn't find it in
the files.
...
Why doesn't tkemc handle the tcp/ip-stack on its own? Or does it?
<

Tcl/Tk can be used to write graphical front ends to command-line programs and
programs that have TCP/IP socket interfaces. If the EMC had either of these
interfaces, it would have made sense to just write a Tcl/Tk script that
connected and just do it all from the script.

However, the EMC uses NML, which is our home-grown communications method that
lets you define shared-memory "mailboxes" that hold C++ data structures for
commands and status. The EMC task controller creates three top-level NML buffers
(command, status, error) that it expects will be connected to by a GUI.
Originally the GUI was Java; then we did the X Toolkit (xemc); then we did
TkEMC. Each of these used NML and the EMC controller has no idea which one is
connecting.

The way TkEMC connects to the EMC is through some C++ code that runs at startup.
Since there is no native Tcl/Tk for this, we had to write our own version of the
windowing shell "wish", called "emcsh". emcsh does everything wish does, plus
handles NML, and adds a bunch of commands for sending NML messages and parsing
NML status.

By default, TkEMC connects directly to shared memory and no sockets are
involved. See the function emcTaskNmlGet() near line 376 in
emc/src/emctask/emcsh.cc for the connection code. The emc.nml file entry for
xemc controls this connection (we double-duty this entry for xemc and TkEMC). If
you change this to "REMOTE" instead of "LOCAL", then the NML code in emcsh will
use sockets instead of shared memory, e.g.,

P xemc emcCommand REMOTE ...
P xemc emcStatus REMOTE ...
P xemc emcError REMOTE ...

This is transparent to the Tcl/Tk script code-- there are no separate statements
specific to either shared memory or socket connections in the TkEMC. You'll have
to dig way down into the NML code in the RCS library to see this.

Note that if you run TkEMC remote, like this, you'll need to run the EMC socket
server "emcsvr" which listens to sockets and then converts back and forth to NML
and accesses the shared memory buffers.

It is possible to write a wish script that talks to the EMC directly, and
doesn't use emcsh as its shell. If you wanted to connect using shared memory,
you'd call the Tcl/Tk commands for shared memory, then reverse engineer the NML
data format and write hideous Tcl/Tk code for handling the bytes. Or, for
sockets, you would write Tcl/Tk code to connect to the socket port set up by
emcsvr directly, and then deal with the socket bytes in your Tcl/Tk code. I have
no idea what format this data is, but Will probably does. Neither option is
recommended.

One reasonable thing to do to get rid of emcsh is to make the code in emcsh.cc a
loadable package, then load it into wish. The tkemc.tcl script would look
something like this:

#!/bin/sh
# the next line restarts using wish \
exec wish "$0" "$-at-"

# load EMC package
load emctcl.o Emc

# now all the defs and NML functions are here, as if we're running emcsh

# the rest is as before

This is a small to moderate amount of work. Chapter 44 of Brent B. Welch's book,
"Practical Programming in Tcl and Tk", shows how to do this in the section on
"Creating a Loadable Package".

--Fred



Date Index | Thread Index | Back to archive index | Back to Mailing List Page

Problems or questions? Contact