
Say, for argument's sake, that I want to make the function printObj() available in Haskell, where:
void printObj (StgClosure *obj);
(as defined in and exported from rts/Printer.c)
In Haskell I want to reflect this as:
printObj :: a -> IO ()
The FFI doesn't really provide for this sort of thing, because it assumes that any data you want to pass to the outside world will be marshaled into something that the far end can understand (a C data structure, say) before being passed. Passing the raw address of the Haskell value on the heap is a bit dodgy, because the RTS will move these objects around from time to time. It's good practice to instead pass a StablePtr to the value. So you really want something like foreign import ccall unsafe printObj :: StablePtr a -> IO () and use deRefStablePtr() inside printObj to get at the real pointer. Note that this might still break in a threaded environment unless you take care to prevent other parts of the system from modifying the heap while you inspect it, but I wouldn't worry too much about that right now.
Alistair mentioned that I could use the FFI to access some C code in the RTS.
My intuition would have been to go about adding a primop as described in /ghc/compiler/prelude/primops.txt (ie without calling through the FFI).
primops are a little harder to add than FFI calls, and are generally used for two reasons: when you want the compiler to know more about the underlying operation (eg. so it can do constant folding) or because the compiler can directly generate inline code for the operation. An FFI call is clearly the way to go here. Cheers, Simon
participants (1)
-
Simon Marlow