Dear Foreign Function Interface,

why does a program like the following fail with a "<<loop>>" exception (using GHC 6.2 on MacOS X)?

import Foreign

main =
        f       <- mkFinPtr finalizer
        fp      <- newForeignPtr f nullPtr
        putStrLn "Hello World"

finalizer ptr = putStrLn ("Finalize "++show ptr++".")

foreign import ccall "wrapper"
        mkFinPtr :: (Ptr () -> IO ()) -> IO (FinalizerPtr ())

Also, does the use of a "wrapper" import constitute a callback from C in the sense of the following statement?

"Whether a finalizer may call back into the Haskell system is system dependent. Portable code may not rely on such callbacks."

I.e. is the above code non-portable?

Why is the ForeignPtr interface constrained to finalizers that are FunPtrs at all? I want to touch a ForeignPtr from another's finalizer to satisfy a liveness dependency (as suggested in the spec). What is the best way to do this?

Suppose I have:

type Thing = Ptr ()
type Subthing = Ptr ()

foreign import ccall "new_thing"
        newThing :: IO Thing
foreign import ccall "new_subthing"
        newSubthing :: Thing -> IO Subthing

 I can't do, as I would like:

foreign import ccall "del_thing"
        delThing :: Thing -> IO ()
foreign import ccall "del_subthing"
        delSubthing :: Subthing -> IO ()

main =
        p1      <- newThing
        p2      <- newSubthing p1
        fp1     <- newForeignPtr delThing p1
        fp2     <- newForeignPtr (\p -> delSubthing p >> touchForeignPtr fp1) p2
        {- more funny things... -}

So because touchForeignPtr is a Haskell function, I must go through a wrapper. It seems strange to me that the Haskell storage manager would not be able to call Haskell routines as finalizers directly...

Assuming that's really the only way to do it, I suppose my code would look like this, correct?

foreign import ccall "&del_thing"
        delThing_p :: FunPtr (Thing -> IO ())
foreign import ccall "del_subthing"
        delSubthing :: Subthing -> IO ()
foreign import ccall "wrapper"
        mkFinPtr :: (Ptr () -> IO ()) -> FunPtr (Ptr () -> IO ())

main =
        p1      <- new_thing
        p2      <- new_subthing p1
        fp1     <- newForeignPtr delThing_p p1
        f       <- mkFinPtr (\p -> delSubthing p >> touchForeignPtr fp1)
        fp2     <- newForeignPtr f p2
        {- the funky chicken... -}

Thanks in advance, Sven Moritz

PS: You're still great!
PPS: Do you mind being called fifi? ;-)

FFI mailing list

Reply via email to