ForeignPtr's - why can't they be passed directly to foreign functions?

Brian Hulley brianh at
Wed Mar 15 06:45:05 EST 2006

Hi -
I've got the beginnings of an API for a GUI system as follows:

data DWindow a
data DEdit a

type Window = DWindow
type Edit a = DWindow (DEdit a)

foreign import ccall duma_init :: IO ()
foreign import ccall duma_run :: IO ()

foreign import ccall duma_release :: FunPtr (Ptr (Window a) -> IO ())

foreign import ccall duma_createEdit :: IO (Ptr (Edit a))
foreign import ccall duma_addTop :: Ptr (Window a) -> IO ()

createEdit :: IO (ForeignPtr (Edit a))
createEdit = do
    edit <- duma_createEdit
    newForeignPtr duma_release edit

addTop :: ForeignPtr (Window a) -> IO ()
addTop w = withForeignPtr w duma_addTop

This works, but it seems a bit of a pain to have to manually convert between 
ForeignPtr's and Ptr's all the time.
In particular, for the definition of addTop, I tried:

foreign import ccall "duma_addTop" addTop :: ForeignPtr (Window a) -> IO ()

but got an error because ForeignPtr's are not allowed as part of the type of 
a foreign function. Since the definition of ForeignPtr is just void *, I 
wonder why this restriction exists - ie is a ForeignPtr not just the same 
address as the corresponding Ptr?

My other question is what happens if I want to have a function that takes 
more than one ForeignPtr as argument ie

foreign import ccall duma_test :: Ptr (Window a) -> Ptr (Window a) -> IO ()

test :: ForeignPtr (Window a) -> ForeignPtr (Window a) -> IO ()
test p q = withForeignPtr p (\p' -> withForeignPtr q $ duma_test p')

Is this the only way to achieve this? It seems a bit long-winded and 
possibly a bit inefficient...

One other question: if I use forkIO within Haskell, am I right in thinking 
that the lightweight concurrent threads are safe to use with my single 
threaded C code ie that there is no danger of a thread being preemptively 
halted while it is inside a foreign function?

Thanks, Brian. 

More information about the Glasgow-haskell-users mailing list