Help: writing ffi bindings to a C library

I want to write a set of bindings to Oracle's OCI library (a low-level C library for doing stuff to the Oracle database). Before I get started, has anyone done this already? (I don't think so, but I'd better ask.) My goal is to start with a simple set of low-level bindings, and build this up to higher-level database abstractions, and to hopefully port HaskellDB (if it's possible). But to start with I simply want to create a set of bindings for the OCI functions and get them working. Trouble is, I have no idea how to start writing a FFI binding. So far I've read: - Haskell 98 FFI Addendum (RC8) : a reference, but not a tutorial. - http://reid-consulting-uk.ltd.uk/docs/ffi.html : incomplete - http://haskell.org/ghc/docs/latest/html/users_guide/hsc2hs.html : is this for writing C that calls Haskell functions? Can anybody point me to a tutorial, or some illustrative examples? At the moment I'm trying to avoid the various ffi tools, and just use the basic ffi capabilities in GHC, so I can get an idea of how it all works. When I'm more comfortable with ffi then I'll think about using the various tools to speed things up. I'm not sure how to treat structures used by the C library. For example, a sample C program might have: int main () { sword rc; OCIEnv *envhp = NULL; OCIServer *srvhp = NULL; OCIError *errhp = NULL; OCISvcCtx *svchp = NULL; OCISession *usrhp = NULL; OCIStmt *stmtp = NULL; ... rc = OCIEnvCreate(&envhp, OCI_DEFAULT, 0, 0, 0, 0, 0, 0); rc = OCIHandleAlloc(envhp, (dvoid**) &errhp, OCI_HTYPE_ERROR, 0, 0); rc = OCIHandleAlloc(envhp, (dvoid**) &srvhp, OCI_HTYPE_SERVER, 0, 0); ... How do I handle values of OCIEnv, OCIServer, etc? I think I'm supposed to use Ptr, ForeignPtr, and Storable to reference them, but I don't see how to combine these types/classes (ForeignPtr takes values of type Ptr a; how do I construct a Ptr a? What type should "a" be?). ***************************************************************** 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. *****************************************************************

On Wed, May 21, 2003 at 04:27:10PM +0100, Bayley, Alistair wrote:
Can anybody point me to a tutorial, or some illustrative examples? At the moment I'm trying to avoid the various ffi tools, and just use the basic ffi capabilities in GHC, so I can get an idea of how it all works. When I'm more comfortable with ffi then I'll think about using the various tools to speed things up.
You could check out what I've done using ffi for darcs. Browse to the files Curl.hs and hscurl.c and hscurl.h at: http://www.abridgegame.org/cgi-bin/darcs?darcs* I've got some sort of scary code in there (threads, pipes and forks in C), but the ffi stuff itself isn't bad at all. ffi really isn't all that hard to use, although I must admit I don't really understand all the options. But what I do know how to do seems to be enough for me.
How do I handle values of OCIEnv, OCIServer, etc? I think I'm supposed to use Ptr, ForeignPtr, and Storable to reference them, but I don't see how to combine these types/classes (ForeignPtr takes values of type Ptr a; how do I construct a Ptr a? What type should "a" be?).
Unless you actually need to ever access their contents, I'd just define the pointers to be of type Ptr (), essentially like a void * pointer in C. No need to use Storable if they are only ever accessed through C functions (which I would hope would be the case). -- David Roundy http://civet.berkeley.edu/droundy/

Agreeing with David, but I like to use
types rather than (). YOu can do this because,
in ghc, you can write:
data Blah
with no rhs, and it is understood to be an 'opaque'
type. Ghc beleives any claims you make about
passing Ptr Blah back and forth to C in your foreign
import declarations <* Grin *>.
As for passing structures back and forth, and
accessing the components, you can do it from Haskell
or from the "c-side"... I can send you a sample of
doing it from haskell if you wish.
Ron
--- David Roundy
On Wed, May 21, 2003 at 04:27:10PM +0100, Bayley, Alistair wrote:
construct a Ptr a? What type should "a" be?).
Unless you actually need to ever access their contents, I'd just define the pointers to be of type Ptr (), essentially like a void * pointer in C. No need to use Storable if they are only ever accessed through C functions (which I would hope would be the case). --
===== ------------------------------------- Ronald Legere rjljr2@yahoo.com ------------------------------------- __________________________________ Do you Yahoo!? The New Yahoo! Search - Faster. Easier. Bingo. http://search.yahoo.com
participants (3)
-
Bayley, Alistair
-
David Roundy
-
Ronald Legere