RE: Help: writing ffi bindings to a C library

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 [mailto:rjljr2@yahoo.com]
Sent: 31 May 2003 15:25
To: Bayley, Alistair; 'haskell-cafe@haskell.org'
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
haskell.
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)
Ron
--- "Bayley, Alistair"
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. *****************************************************************

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/
participants (2)
-
Bayley, Alistair
-
Marcin 'Qrczak' Kowalczyk