Squeak SmalltalkJoker Squeak Smalltalk : Image VM OS Application : prevnext Callbacks How To Implement

Actually, it's not all that hard to support callbacks. Back, when I wrote
the FFI I considered supporting callbacks but the major reason against it
was not the complexity but time constraints (the project we were working on
really needed it). If you wanted to do callbacks all you need to keep in
mind that the only, the exclusive place where a regular (not interrupt)
callback can occur is during a primitive call (obviously - all other methods
only run bytecodes and send further messages). Because of this, the entire
internal interpreter state is perfectly externalized so that it is quite
doable do simply "call back" into interpret(). So what you'd have to do is
essentially:

- define a number of callback stubs (could be a fixed number) which
    - remember the stack pointer for later use (to get the arguments)
    - mark itself as the "top-most C frame" being used
    - signal the callback semaphore associated with the stub
    - mark the execution point by a setjmp()
    - call interpret()
    - (after return through longjmp()) restore the prior top-most C frame
    - returns to caller

- define the "return from callback" primitive so that it
    - horribly barfs if it's not the top-most callback
      (this would mean you try to return through another C stack frame)
    - simply leaves interpret() by a longjmp to the callback stub

This should work just nicely - a bit of trickery is certainly needed but not
very much. Then, on the Squeak side what you do is:

- provide a Squeak process for each callback which
    - requests a new callback stub
    - sits waiting on the callback semaphore
    - when it wakes up requests the stack pointer
    - unpacks the arguments from the stack (via a few FFI primitives)
    - runs the associate callback block
    - returns via return from callback primitive

That's about it. If you want to get fancy you can add some stuff in the
Squeak process that serializes the returns appropriately so that callbacks
invoked from different processes work appropriately. But really, supporting
callbacks isn't all THAT hard ;-)

Cheers,
  - Andreas

> and I was hoping someone had
> some bright suggestions for me. I need to send an arbitrary message
> to an arbitrary object in Squeak from within C. I have spent a lot
> of time reading the Interpreter and ObjectMemory code, but can not
> find a quick primitive to do this. Is there some mechanism for
> looking up method objects that does not have side effects on the VM
> state. Specifically I need the mechanism to implement call backs
> from C, and can not find a simple function for doing this lookup
> without side effects.
If you are really into implementing callbacks, check out the stuff I
wrote in:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2004-
February/073231.html
However, I would advise you to very carefully think about whether you
really *have* to have callbacks. In most cases you should be able to
"get by" with a varying number of workarounds. Depending on your
concrete constraints (which I have no idea about - it may be helpful
to explain in more detail what you are working on) you might be able
to use one of the following alternatives:
- if the message sent from C does not have to complete synchronously,
you can simply signal a semaphore. This is precisely what (for
example) the async I/O, network and similar primitives do. Then, a
Squeak process can pick up the request (such as the message name) via
a primitive and run the remaining stuff from within Squeak.
- if the above is not an option because you need the message to be
processed synchronously to return a result, consider running "all of
your C code" in a separate thread. This would allow you to utilize the
same mechanism as the above, except that now the C thread could block
until the result has been computed and is returned from Squeak (via an
appropriate primitive which releases the C thread).
In any case, you will have a hard time if you try to do all of this
stuff directly from C and I would advise strongly against the idea of
"sending a message from C". Try to combine both areas and have Squeak
do what it does best - dealing with messages and sending them.
Cheers,
  - Andreas