Haskell FFI bindings for Augeas

I’ve published my first Haskell project on hackage.  Augeas, is a FFI binding for the Augeas API. I wrote it mainly to learn about Haskell’s FFI, and to keep busy while I was between jobs.  Also the API was small enough that it was a managable project.

Chapter 17 of Real World Haskell was very helpful during the project, however it didn’t cover file pointers, which were needed for the aug_print method.

The Bzlib2 Binding article in issue 2 of the Monad Reader, showed me how to do the Handle to CFile conversions, but I ran into some problems with their handleToCFile method during testing.

In my aug_print test, I was confused why I could no longer write to the Handle after calling aug_print. Eventually I found out that handleToFD closes the Handle passed to it.

I got around this by calling hDuplicate on the handle, and then calling handleToFD on the duplicate instead.

handleToCFile :: Handle -> String -> IO (Ptr CFile)
handleToCFile h m =
 do iomode <- newCString m
 
    -- Duplicate the handle, so the original stays open
    -- after the handleToFd call closes the duplicate
    dup_h <- hDuplicate h
    fd <- handleToFd dup_h
    fdopen fd iomode

Also, I made sure to close the Fd as well, which the Bzlib2 Bindings article did not show:

aug_print :: Ptr Augeas  -- ^ Augeas pointer
          -> Handle      -- ^ Already opened file handle
          -> ByteString  -- ^ PATH
          -> IO (AugRet) -- ^ return value
aug_print aug_ptr fptr_out bs_path =
    do
      useAsCString bs_path $ \path -> do
        out <- handleToCFile fptr_out "w"
        ret <- c_aug_print aug_ptr out path
        fflush out
        fclose out
        return(ret)

Leave a Reply

You must be logged in to post a comment.