Allocation & Marshalling Question (again)

Adrian Hey ahey at iee.org
Fri May 30 03:34:30 EDT 2003


On Thursday 29 May 2003 16:06, Wolfgang Thaller wrote:
> > Whoops, now I see a real problem with what I'm asking for.
> >
> > I guess since the (hypothetical) withCString is creating
> > a new CString (bit like an IORef) it should have type
> >
> >   withCString :: String -> (CString -> b) -> IO b
>
> It's still highly dangerous. When will the string be freed (no you
> can't rely on the garbage collector, because a CString is a Ptr and not
> a ForeignPtr; so the string has to be freed explicitly).

If it's implementation was similar to current withCString your right I guess. 
I was assuming that the (hypothetical) new implementation of withCString was
not constrained in this way (I.E. did proper garbage collection on whatever
structures it allocated). I don't think it's possible for users to implement
this themselves using the FFI as it is (well I haven't managed it), but with
some behind the scenes black magic I still think it should be possible
(in principle).

If this is so, AFAICS the only reason the result type needs to be IO b is 
because whatever the pointer points to is potentially mutable (like an
IORef). So I don't think we can have..
        withCString :: String -> (CString -> b) -> b
for the same reason that we can't have..
	newIORef :: a -> IORef a

Maybe we could also have something like this to avoid marshalling the
same string again and again..
	unsafeWithConstCString :: String -> (CString -> b) -> b
	unsafeWithConstCString s f = unsafePerformIO $ withCString s f 
..but only use this with functions which promised not to mutate the
CString. 

> > and I guess my <+ should be..
> >   (<+) :: (a -> b) -> ((a -> IO b) -> IO b) -> IO b
> >   f <+ alloc = alloc $ \p -> return $ f p
> >
> > (Well at least that's got rid of the unsafePerformIO :-)
> >
> > Would this be safe?
>
> It would probably be safer than the version with the unsafePerformIO,
> but still:
>
> foreign import ccall foo :: CString -> Word32 -> Word32
>
> main = do
> 	bar <- foo <+ withCString "Hello, world."
> 	print (bar 42)
>
> ... same problem as above.

Oh dear, you're right of course.
Still not safe. Sigh.

Regards
--
Adrian Hey




More information about the FFI mailing list