Simon Marlow simonmar@microsoft.com
Tue, 19 Mar 2002 11:59:46 -0000

> 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=20
	   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

> 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=20
> described in
> /ghc/compiler/prelude/primops.txt (ie without calling through=20
> 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. =20

An FFI call is clearly the way to go here.