Allocation & Marshalling Question (again)
Wolfgang Thaller
wolfgang.thaller at gmx.net
Wed May 28 05:51:19 EDT 2003
> 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?
>
> Wouldn't..
> allocaBytes :: Int -> (Ptr a -> b) -> b
> ..be more useful?
Why? What could the pure function you're passing to allocaBytes do with
the pointer?
When would the storage be freed again? The original allocaBytes frees
it after the IO action has finished, but before returing itself. How
would that apply to the pure version?
>
> To get around this I defined an operator..
> infixl 0 <+
> (<+) :: (Ptr a -> b) -> ((Ptr a -> IO b) -> IO b) -> b
> f <+ alloc = unsafePerformIO $ alloc $ \p -> return $ f p
What can f do with the pointer, outside the IO monad, without using
unsafePerformIO itself?
Also, if you're passing alloca or allocaBytes for the alloc parameter,
how do you make sure that 'f' has been _completely_ evaluated before
alloca deallocates the storage again?
> Possible explanations that occur to me are..
> 1- It's technically impossible.
> 2- It's unnecessary because FFI users can define their own
> contraptions like
> <+ if they want them, assuming the use of unsafePerformIO in this
> context
> really is safe (and unsafePerformIO is available).
> 3- It's undesirable because the existing forms are better in some way.
> 4- It's undesirable because it would break existing code (not true
> AFAICS).
5- because this use of unsafePerformIO is highly dangerous (I think it
will lead to segfaults sooner or later) and should be avoided at all
costs.
Also,
6- because a pure function cannot do anything useful with a pointer,
IMHO.
Cheers,
Wolfgang
More information about the FFI
mailing list