Help: writing ffi bindings to a C library

Bayley, Alistair
Mon, 2 Jun 2003 08:58:07 +0100

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). The idea was to write the Haskell-C bindings at as low a level as
possible (i.e. directly to the OCI libraries), and then build up from there.
Although the bindings may be ugly, I thought it would have been easier to
build higher layers in Haskell rather than C.

However, if you think it's probably better to build the first layer in C,
then I'll do that.

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 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

Or must C functions that are to be called from Haskell return results only
in the return value?

-----Original Message-----
From: Ronald Legere []
Sent: 31 May 2003 15:25
To: Bayley, Alistair; ''
Subject: RE: Help: writing ffi bindings to a C library

One strategy is to wrap that funtion in another
function (in C) that encapsulates the 'typical'
call you want to make. THen import this function into
In any event, start with something simpler, to 
get the hang of it. Try to write a function (in C)
that adds two integers,or prints something and import
that in to haskell. There are some examples floating
around to get you started, but I can't
find them at the moment on the CVS tree.  Anyone?

Also, read "Tackling the awkward squad" (Google it)


--- "Bayley, Alistair"
<> wrote:
> So...
> I'm still trying to write this Oracle OCI ffi
> binding. Can anyone tell me
> how to declare the Haskell type for this function:
> sword   OCIEnvCreate (OCIEnv **envp, ub4 mode, dvoid
> *ctxp,
>                  dvoid *(*malocfp)(dvoid *ctxp,
> size_t size),
>                  dvoid *(*ralocfp)(dvoid *ctxp,
> dvoid *memptr, size_t
> newsize),
>                  void   (*mfreefp)(dvoid *ctxp,
> dvoid *memptr),
>                  size_t xtramem_sz, dvoid
> **usrmempp);
> Note that when I use it, I'm passing 0 (NULL) into
> almost all of the args,
> so the usage in C is typically:
> 	rc = OCIEnvCreate(&envhp, OCI_DEFAULT, 0, 0, 0, 0,
> 0, 0);
> i.e. I don't care about most of the args, so that
> should make the Haskell
> declaration simpler. Some of the arguments are
> pointers to functions, for
> example.
> What I can't figure out is how to declare the type
> of the first arg. Is is
> Ptr (Ptr OCIEnv) ?
> Here's what I have so far (not much, I know):
> > module Main where
> > import Foreign
> > import Foreign.C.Types
> > import Foreign.C.String
> > import Foreign.Ptr
> > data OCIEnv
> > foreign import ccall "oci.h OCIEnvCreate"
> ociEnvCreate :: Ptr OCIEnv ->
> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int

The information in this email and in any attachments is 
confidential and intended solely for the attention and use 
of the named addressee(s). This information may be 
subject to legal professional or other privilege or may 
otherwise be protected by work product immunity or other 
legal rules.  It must not be disclosed to any person without 
our authority.

If you are not the intended recipient, or a person 
responsible for delivering it to the intended recipient, you 
are not authorised to and must not disclose, copy, 
distribute, or retain this message or any part of it.