Allocation & Marshalling Question (again)

Malcolm Wallace Malcolm.Wallace at cs.york.ac.uk
Thu May 29 08:56:42 EDT 2003


Adrian Hey <ahey at iee.org> writes:

> > > So excuse me if this seems half baked, but am I the only one who
> > > thinks the type signatures of utilities like this..
> > >      allocaBytes :: Int -> (Ptr a -> IO b) -> IO b
> > > ..are rather inconvenient?

I don't think the types are really as inconvenient as you suggest.
To go back to your original posting a couple of weeks ago...

> I think it would be nice to free users from this style of programming..
>   g s n f =
>	withCString s    $ \sPtr    ->
> 	allocaBytes n    $ \buffPtr ->
> 	withForeignPtr f $ \fPtr    ->
> 	do g' sPtr buffPtr fPtr
>
>   g' :: CString -> Ptr a -> Ptr b -> IO c

... you suggested that what you would really like to write instead is just

    g :: String -> Int -> ForeignPtr a -> IO c
    g s n f = g' <+ withCString s <+ allocaBytes n <+ withForeignPtr f

In order to make this work with your definition of <+, you needed to
change the types.  But perhaps that was because your definition of <+
was not exactly what you needed.

How about the following alternative:

    g s n f = g' <$ withCString s <+ allocaBytes n <+ withForeignPtr f

    infixl 3 <$
    a <$ b = b a

    infixr 4 <+
    f <+ g = \h-> f $ \a->
                  g $ \b->
                  h a b

which preserves all the types exactly as they are in the FFI standard?
This avoids the whole question of introducing unsafePerformIO inside
the <+ combinator, thus also avoiding its unsafety.  Should you
happen to want to marshall this way in the middle of pure non-IO code,
then you can wrap a single unsafePerformIO at the outer level, e.g.

    g :: String -> Int -> ForeignPtr a -> c
    g s n f = unsafePerformIO $
              do g' <$ withCString s <+ allocaBytes n <+ withForeignPtr f

which is much more likely to preserve safety than having multiple
embedded calls.

Regards,
    Malcolm



More information about the FFI mailing list