ForeignPtr's - why can't they be passed directly to foreign functions?

Simon Marlow simonmarhaskell at gmail.com
Wed Mar 15 11:09:46 EST 2006


Brian Hulley wrote:

> I've got the beginnings of an API for a GUI system as follows:
...
> addTop :: ForeignPtr (Window a) -> IO ()
> addTop w = withForeignPtr w duma_addTop
> 
> This works, but it seems a bit of a pain to have to manually convert 
> between ForeignPtr's and Ptr's all the time.
> In particular, for the definition of addTop, I tried:
> 
> foreign import ccall "duma_addTop" addTop :: ForeignPtr (Window a) -> IO ()

This is the way it used to be in GHC before the FFI.  In the FFI we 
moved to withForeignPtr instead.  IIRC, the motivation was something 
along these lines:

  - allowing ForeignPtr to be passed directly to a foreign function
    implies some magic that happens at the point of the foreign call
    to convert the ForeignPtr to a Ptr.

  - there also has to be some magic to ensure that the ForeignPtr
    couldn't be finalized until the call returns.  This amounted to
    adding a touch# primitive to keep the ForeignPtr alive over the call.
    So internally the compiler was doing something like withForeignPtr
    anyway.  This behaviour is quite hard to explain in the spec,
    withForeignPtr is much simpler.

  - We wanted withForeignPtr anyway, to avoid having to duplicate all the
    marshalling operations that operate on Ptr.

So, given that we wanted withForeignPtr anyway, there was no need to 
also have the compiler do its internal magic to allow ForeignPtr to be 
used as an FFI argument.  Also, this means GHC doesn't need a primitive 
ForeignPtr type (the primitive Ptr type is enough).

Later on, we discovered that the withForeignPtr interface enables a much 
more efficient representation of ForeignPtr.  This is coming in GHC 6.6.

Cheers,
	Simon


More information about the Glasgow-haskell-users mailing list