[Openmcl-devel] Using Cocoa with MCL

Yannick Versley yversley at gmx.de
Sat May 10 03:00:43 PDT 2003

> There might be some way to do what #_setjmp does (establish something
> like a CATCH frame that #_longjmp can do something like THROW to).  It
> probably won't ever "work" to use #_setjmp from lisp (as if #_setjmp
> was just a normal function call and not magic),
Well, you *can* just call _setjmp like a normal function. It then sets up
a jump buffer to the FFI entry/exit routine, and, ideally, an error would
land you not at the point where you called _setjmp, but somewhere in
Lisp-land where you called the function that threw the exception, and
you can (almost) easily check for exceptions via some unspectacular C
functions. It's a hack and it seems to sometimes collide with either the
Lisp scheduler or the GC.

> but it seems like it
> may be possible to do something like:
> (rlet ((buf :jmp_buf))
>   (catch :some-tag
>    (%%associate-jmp-buf-with-current-catch-frame buf)
>    (progn
>      (whatever)))) ; that association needs to be broken; perhaps
>                      this'd work better if it was nested differently
> If a jmp_buf was "associated" with a catch frame (and this all worked),
> then #_longjmp to that jmp_buf would behave exactly like a THROW to
> that frame's tag.  There are lots of gory details and complications,
> but this might (with suitable macrology to hide those details) make
> it possible to write ObjC-visible exception handlers in lisp.
This would mean recreating almost all of the black magic that
currently works in the FFI entry/exit point. I looked at it, understood
some of it and concluded that it's not a feasible thing for people like me
who are happy to understand half of the weird things going on at assembly

> The next nasty surprise awaiting us is the observation that merely
> transferring control to the right place (via #_longjmp) isn't
> adequate: THROW "unwinds the stack" on the way to its target,
> discarding intervening CATCH frames and executing intervening
> UNWIND-PROTECT cleanup forms.  If there's a reasonably sane way to
> patch #_longjmp (kind of sounds like an oxymoron already) so that it
> does the right thing, it seems like it'd be worth the effort to do
> so.
I was thinking of simply wrapping the lisp function that invokes an ObjC
method (and is called by all ObjC method invocations) with the
_setjmp/error checking mechanism and rethrowing occuring exceptions on the
Lisp side. The _setjmp business would be concentrated in _one_ location
and there would not be any need for much macrology or patching the
longjmp C routine.

> The ObjC runtime maintains a per-thread LIFO list of exception
> handlers; THROW is ordinarily blissfully unaware of this.  I'm not
> sure how to effect this, but throwing "past" an ObjC exception
> handler should ideally remove that handler from the per-thread
> list.
If we wrap Lisp implementations of ObjC methods with a wrapper that
handles Lisp exceptions and rethrows them as ObjC exceptions (in some sane
way), we wouldn't have to think about unwinding ObjC handlers, but we
would still have the same problems as the Java/ObjC wrapper currently has
(means: Lisp exceptions thrown through ObjC code get horribly munged).

Possibly, all this would be easier if we had some kind of native interface
like JNI in Java that allows C code to interact with Lisp data and code in
a clean and easy way.
And, yes, a pony for me too ;-)


Openmcl-devel mailing list
Openmcl-devel at clozure.com

More information about the Openmcl-devel mailing list