Another silly primitive question

Chris Reuter cgreuter at calum.csclub.uwaterloo.ca
Tue Feb 16 20:22:59 UTC 1999



On Tue, Feb 16, 1999 at 01:04:23PM -0500, Lex Spoon wrote:
[...]
> An alternative is to write the primitives in straight C, instead of
> writing in Smalltalk and translating to C.  I see two basic kinds of
> primitives, one of which this alternative seems good for.
[...]
> On the other hand, there are primitives intended for low-level OS access
> that Squeak doesn't understand.  For instance, adding pipes or Unix
> domain sockets.  These kind of primitives tend to be pretty short, and
> furthermore they aren't able to run under in Smalltalk.  For these, it's
> probably *easier* to just write the C code directly.  The primitives are
> unlikely to actually run in Smalltalk, anyway, so you have the same
> edit-compile-restart cycle.

Yeah, I agree.  There's a lot of stuff I can't do in Squeak because I
need access to some library or other.  The thing is, writing
primitives is _hard_.

I did some thinking about this sort of thing a few months back. 

In my Real Job[tm], I'm currently writing software in a combination of
C and Tcl/Tk.  Most of the Real Stuff is done in C with the UI and
related easy bits[1] done in Tcl.

Tcl has its faults, but its interface to C is the most elegant that
I've seen.  A glue function gets an integer (argc) and an array of
strings[1] (argv).  A bunch of functions are provided to convert the
individual arguments to C data types.  For example, "Tcl_GetInt" will
attempt to convert its argument to an integer.  On failure, it returns
an error code and sets the error flag in the interpreter so all the
glue routine has to do is return the constant TCL_ERROR.  If you want
to do something fancy, you can always ignore the error and try again.

I was able to write quite a lot of them easily using cut+paste and
search+replace.  (I found out too late that swig would have done all
this for me.  Oh well...)

In contrast, linking to external C[2] code from Squeak requires:

   1) Writing a CrossTalk[3] method and adding it to the interpreter. 
   2) Writing C routine to launder the arguments.
   3) Decoding object headers to check types, get lengths and do
      general Object-to-C-type conversion.
   4) Doing the reverse when returning values to Squeak.

This whole series of operations is way more work than I want to do
just to be able do a getenv, not to mention being really, really
dangerous.  Mucking around the object memory has to be done right or
you'll introduce corruptions into the image, not the sort of thing I
want to debug.

So, my thoughts went, why not write a Tcl-style API for calling native
functions from Squeak?  There would be a small set of primitives and
accompanying C routines to convert Squeak objects (at least a small
subset thereof) to C types, copying them to an external data
structure, and passing this structure to the external C glue routine.
The glue routine would then use another group of functions to test for
type and possibly retrieve the data, just like the Tcl_Get* functions.
A similar set of routines would allow one or more objects to be
returned to the caller.

I haven't given too much thought to what the Smalltalk end would look
like--probably a class "ExternalLibrary" that handles dynamic loading
and implements methods like #invokeExternal:withArgs: and subclasses
for specific commonly-used libraries.

This setup has the advantages of being simple, easy to use and a lot
safer, since all the hairy stuff is hidden.  Also, because the
external routines never need to touch the image, we can mark the
object memory as read-only (on those platforms that support it[4])
just before calling the glue routine and unlock it afterward.  That
way, if there's an image-trashing bug, it will immediately come to
light.  (Performance considerations might make this feasable only as a
debugging tool.)

I actually started hacking together the beginnings of the above, but
then I started hearing about pluggable primitives so shelved it lest I
reinvent the wheel, badly.  I haven't had a chance to look at them yet
so I don't know if the above still has any worth.  I thought I'd throw
out the ideas, anyway.


				--Chris



[1] Which, it turns out, are not necessarily that easy.  Tcl is
actually a relatively decent language in its own right (but nowhere
near as good as Smalltalk).

[2] Substitute your favourite compiled programming language.

[3] My proposal for the offical catchy name for the subset of
Smalltalk that can be translated to C.

[4] I know it can be done under UnixWare, Linux, OS/2 and Win16 (via
some DMPI calls in assembly language--ick).  I would guess that the
rest must also have some way of doing this, since they all have MMUs.





More information about the Squeak-dev mailing list