Help: writing ffi bindings to a C library

Marcin 'Qrczak' Kowalczyk qrczak@knm.org.pl
Mon, 2 Jun 2003 11:45:43 +0200


Dnia pon 2. czerwca 2003 09:58, Bayley, Alistair napisał:

> Yes, I had considered this (writing an abstraction layer in C). I have
> decided initially to try doing it in Haskell, because I thought that
> Haskell would be a better choice for writing abstraction layers (not as
> verbose as C).

You can write it in Haskell too and I would recommend that - unless the C 
library uses some passing convention Haskell cannot handle (e.g. passing 
structs by value, or having variable argument count, or relying heavily on 
macros).

> Getting back to my question, can I use functions that take twice-deref'ed
> pointers as args? This is a function that effectively returns some of its
> work in "out" arguments

Sure. You can use libraries documented in the Haskell FFI proposal.

> e.g. a C function like this:
>
>     int someCFunction(SomeType **ptrptr, int i)
>
> (It would create an opaque structure and point *ptrptr at it. If it fails
> then it would return a negative value.)
>
> Is it simply a case of declaring it like this (in ghc):
> > data SomeType
> > type SomeTypeRef = Ptr SomeType
> > foreign import ccall "blah.h someCFunction" someCFunction ::
> >    Ptr SomeTypeRef -> Int -> Int

foreign import ccall "blah.h someCFunction" someCFunction ::
   Ptr SomeTypeRef -> CInt -> IO CInt

haskellWrapper :: Int -> IO (Maybe SomeTypeRef)
haskellWrapper arg =
   alloca $ \ptr -> do
      res <- someCFunction ptr (fromIntegral arg)
      if res < 0 then return Nothing else liftM Just (peek ptr)

You can raise an IO error instead. You can wrap the result in a ForeignPtr if 
it should be finalized when it's garbage collected.

You can use hsc2hs to access integer constants, enumeration values and structs 
from Haskell, or write C wrappers inline inside Haskell source (e.g. to turn 
macros into functions).

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/