Type of newForeignPtr & addForeignPtrFinalizer

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
participants (1)
-
Adrian Hey