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