Type of newForeignPtr & addForeignPtrFinalizer
Adrian Hey
ahey@iee.org
Sun, 7 Jul 2002 07:46:59 +0100
Hello,
I have a feeling this may be a stupid question, but why are the
types of these..
newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)
addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO ()
(second arg being the finalizer)
Won't a finaliser almost always take a pointer to the thing being
finalised as an argument? If so it would be more convienient
to have newForeignPtr..
newForeignPtr :: Ptr a -> (Ptr a -> IO ()) -> IO (ForeignPtr a)
or maybe..
newForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO (ForeignPtr a)
and..
addForeignPtrFinalizer :: ForeignPtr a -> (ForeignPtr a -> IO ()) -> IO ()
The first of these is easy to implement yourself I suppose..
myNewForeignPtr :: Ptr a -> (Ptr a -> IO ()) -> IO (ForeignPtr a)
myNewForeignPtr p fin = newForeignPtr p (fin p)
The second seems to require this bit of weirdness..
myNewForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO (ForeignPtr a)
myNewForeignPtr p fin = do
newfp <- newForeignPtr p (return ())
addForeignPtrFinalizer newfp (fin newfp)
return newfp
Unless I'm missing something, you have to use a pointless dummy
finaliser (return ()) to get a ForeignPtr to use as the argument
of the real finaliser.
The reason I ask is I've been trying to use C2HS recently to
produce a Haskell binding to GNU plot library, and have had
to do something very similar. The relevant bits of .chs file
being..
-- Haskell: newtype Plotter = Plotter (ForeignPtr Plotter)
{#pointer *plPlotter as Plotter foreign newtype#}
-- Haskell: newtype PlotterParams = PlotterParams (ForeignPtr PlotterParams)
{#pointer *plPlotterParams as PlotterParams foreign newtype#}
-- Destructor for the plPlotter type.
-- C proto: int pl_deletepl_r (plPlotter *plotter);
-- Haskell: deletePlotter :: Plotter -> IO ()
{#fun unsafe pl_deletepl_r as deletePlotter
{id `Plotter'} -> `()' -- id as marshaller??
#}
-- Create a new X Plotter
-- C proto: plPlotter* new_x_plotter (plPlotterParams* plotter_params);
-- Haskell: newXPlotter :: PlotterParams -> IO Plotter
-- newXPLotter'_ :: PlotterParams -> IO (Ptr Plotter)
{#fun unsafe new_x_plotter as newXPlotter
{id `PlotterParams'} -> `Plotter' marshalPlotter *
#}
marshalPlotter :: Ptr Plotter -> IO Plotter
marshalPlotter p = do
foreignPlotter <- newForeignPtr p (return ())
let plotter = Plotter foreignPlotter
addForeignPtrFinalizer foreignPlotter (deletePlotter plotter)
return plotter
I suppose the thing that's worrying me most is will this work?
(I don't have enough done yet to find out). It seems overly
complicated to me, but I can't see any alternative to this
complexity. Am I using C2HS right? Have I missed something
obvious?
Thanks
--
Adrian Hey