| 5 | | [[GhcFile(rts/Adjustor.c)]] |
| | 5 | |
| | 6 | == Foreign Import "wrapper" == |
| | 7 | Files [[GhcFile(rts/Adjustor.c)]] [[GhcFile(rts/AdjustorAsm.S)]]. |
| | 8 | |
| | 9 | Occasionally, it is convenient to treat Haskell closures as C function pointers. |
| | 10 | This is useful, for example, if we want to install Haskell callbacks in an existing C library. |
| | 11 | This functionality is implemented with the aid of adjustor thunks. |
| | 12 | |
| | 13 | An adjustor thunk is a dynamically allocated code snippet that allows |
| | 14 | Haskell closures to be viewed as C function pointers. |
| | 15 | |
| | 16 | Stable pointers provide a way for the outside world to get access to, |
| | 17 | and evaluate, Haskell heap objects, with the RTS providing a small |
| | 18 | range of ops for doing so. So, assuming we've got a stable pointer in |
| | 19 | our hand in C, we can jump into the Haskell world and evaluate a callback |
| | 20 | procedure, say. This works OK in some cases where callbacks are used, but |
| | 21 | does require the external code to know about stable pointers and how to deal |
| | 22 | with them. We'd like to hide the Haskell-nature of a callback and have it |
| | 23 | be invoked just like any other C function pointer. |
| | 24 | |
| | 25 | Enter adjustor thunks. An adjustor thunk is a little piece of code |
| | 26 | that's generated on-the-fly (one per Haskell closure being exported) |
| | 27 | that, when entered using some 'universal' calling convention (e.g., the |
| | 28 | C calling convention on platform X), pushes an implicit stable pointer |
| | 29 | (to the Haskell callback) before calling another (static) C function stub |
| | 30 | which takes care of entering the Haskell code via its stable pointer. |
| | 31 | |
| | 32 | An adjustor thunk is allocated on the C heap, and is called from within |
| | 33 | Haskell just before handing out the function pointer to the Haskell (IO) |
| | 34 | action. User code should never have to invoke it explicitly. |
| | 35 | |
| | 36 | An adjustor thunk differs from a C function pointer in one respect: when |
| | 37 | the code is through with it, it has to be freed in order to release Haskell |
| | 38 | and C resources. Failure to do so will result in memory leaks on both the C and |
| | 39 | Haskell side. |
| | 40 | |