6.32.7 Callbacks

In some cases you have to pass a function pointer to a C function, i.e., the library wants to call back to your application (and the pointed-to function is called a callback function). You can pass the address of an existing C function (that you get with lib-sym, see Low-Level C Interface Words), but if there is no appropriate C function, you probably want to define the function as a Forth word. Then you need to generate a callback as described below:

Callbacks use a staged approach: First you define a callback instantiator for a certain stack effect; then you use the instantiator to produce a C function pointer from an xt (the prototype of the C function is derived from the Forth stack effect); and finally you can use the resulting C function pointer in a context that needs it.

You can generate a callback instantiator with:

c-callback ( "forth-name" "{type}" "—" "type" –  ) gforth-1.0

Define a callback instantiator with the given signature. The callback instantiator forth-name ( xt -- addr ) takes an xt, and returns the address of the C function handling that callback.

c-callback-thread ( "forth-name" "{type}" "—" "type" –  ) gforth-1.0

Define a callback instantiator with the given signature. The callback instantiator forth-name ( xt -- addr ) takes an xt, and returns the address of the C function handling that callback. This callback is safe when called from another thread

Each instantiator can be called callback# times, and thus can generate that number of callbacks, with the relevant value of callback# being the one at the time when the instantiator is defined. I.e., you can determine that number for an instantiator by changing the value callback# before defining the instantiator. In other words, you need to follow a static allocation discipline for the callbacks.

callback# ( – n  ) gforth-experimental “callback-number”

N is the number of instantiations that the next callback instantiator can create. This number can be changed with to callback#, and affects the callback instantiators defined after this change.

Here is an example of a callback use with all stages:

c-library callback-test
\c typedef void (*rr2v)(double,double);
\c void testrr2v(rr2v f) {f(0.5,1.5);} /* function that calls a callback function f */
c-function testrr2v testrr2v a -- void
c-callback rr2v-callback r r -- void   \ define callback instantiator
end-c-library
: printrr fswap f. f. ;
' printrr rr2v-callback constant printrr-c \ generate a callback instance
printrr-c testrr2v \ use the callback function pointer by passing it to testrr2v