Next: , Previous: Smalltalk callin, Up: C and Smalltalk

5.6 Smalltalk blocks as C function pointers

The Smalltalk callin mechanism can be used effectively to construct bindings to C libraries that require callbacks into Smalltalk. However, it is a “static” mechanism, as the callback functions passed to the libraries have to be written in C and their type signatures are fixed.

If the signatures of the callbacks are not known in advance, and the only way to define callbacks is via C function pointers (as opposed to reflective mechanisms such as the ones in GTK+), then the VMProxy functions for Smalltalk callin are not enough.

gnu Smalltalk provides a more dynamic way to convert Smalltalk blocks into C function pointers through the CCallbackDescriptor class. This class has a constructor method that is similar to the cCall: annotation used for callouts. The method is called for:returning:withArgs: and its parameters are:

The array passed as the third parameter represents values that are passed from C to Smalltalk and, as such, should be filled with the same rules that are used by the return type of a C callout. In particular, if the C callback accepts an int * it is possible (and indeed useful) to specify the type of the argument as #{CInt}, so that the block will receive a CInt object.

Here is an example of creating a callback which is passed to glutReshapeFunc1. The desired signature in C is void (*) (int, int).

     | glut |
     glut glutReshapeFunc: (CCallbackDescriptor
         for: [ :x :y | self reshape: x@y ]
         returning: #void
         withArgs: #(#int #int))

It is important to note that this kind of callback does not survive across an image load (this restriction may be lifted in a future version). When the image is loaded, it has to be reset by sending it the link message before it is passed to any C function. Sending the link message to an already valid callback is harmless and cheap.


[1] The GLUT bindings use a different scheme for setting up callbacks.