FFI Ptr question

Sven Panne Sven.Panne@informatik.uni-muenchen.de
Thu, 03 Jul 2003 13:42:19 +0200


paul@theV.net wrote:
 > So am I right to draw a picture like this? [...]

Basically, yes. Or from the Haskell implementation's view:

    "I don't have a clue what a Ptr really is, but it fits in C's void*."

 > [ 1. & 2. ]

The requirement for matching allocators and deallocators is not much
different from the situation in e.g. C++: You can't "free" an object
constructed via "new", you can't simply "delete" an array allocated
with "new[]", etc.

 > 3. If the Haskell Ptr is no longer in use, the Haskell GC will
 >    collect it, regardless of whether it has a dangling pointer
 >    to Foreign Data Block.

It is by no means clear if the pointer is "dangling", even if Haskell
knew that a Ptr is really a pointer. Other C pointers or Haskell Ptrs
could still reference the data.

What the best approach is, depends on your problem:

a) The C part does more than a simple malloc/free in its
    (de-)allocation functions, but the lifetime of the object is
    restricted. In this case, a "withNewFoo" Haskell action is often a
    good approach, e.g.:

       withNewFoo :: (Ptr a -> IO b) -> IO b
       withNewFoo = bracket c_alloc c_dealloc

       foreign import ccall unsafe "c_alloc" c_alloc :: IO (Ptr a)
       foreign import ccall unsafe "c_dealloc" c_dealloc :: Ptr a -> IO ()

b) Same as a), but the lifetime of the C object should be under
    control of the Haskell GC. In this case, you can use a ForeignPtr,
    which is basically a Ptr with attached finalizers.

c) If the C part simply needs a buffer for some time, there are quite
    a few possibilities, depending on the required lifetime and
    ownership of the buffer:

    * explicit control via Foreign.Marshal.Alloc.malloc and
      Foreign.Marshal.Alloc.free

    * pooled allocation ("all or nothing") via Foreign.Marshal.Pool

    * Foreign.ForeignPtr.mallocForeignPtr* puts the buffer under
      control of Haskell's GC

    * explicitly delimited lifetime via Foreign.Marshal.Alloc.alloca

 > I only hope the Ptr part of FFI documentation can include some of
 > the malloc/free guidelines, otherwise it is quite confusing for
 > beginners.

The FFI spec is, well, a spec and not intended as a tutorial, but
Alastair has written a guide to the FFI:

    http://www.reid-consulting-uk.ltd.uk/docs/ffi.html

Cheers,
    S.