[Haskell-cafe] Re: How to deal with pointers to pointers in the FFI
Ben Franksen
ben.franksen at online.de
Fri Oct 17 18:29:32 EDT 2008
Jefferson Heard wrote:
> I have the following functions in C:
>
> OGRErr OGR_G_CreateFromWkb (unsigned char *, OGRSpatialReferenceH,
> OGRGeometryH *, int)
> OGRErr OGR_G_CreateFromWkt (char **, OGRSpatialReferenceH,
OGRGeometryH
> *)
> void OGR_G_DestroyGeometry (OGRGeometryH)
> OGRGeometryH OGR_G_CreateGeometry (OGRwkbGeometryType)
>
> The normal sequence of calls is
>
> OGRGeometryH handle = OGR_G_CreateGeometry(SOME_TYPE);
> // do stuff
> OGR_G_DestroyGeometry(handle);
>
> OR
>
> OGR_G_CreateFromWkb(blob, ref, &handle, 0);
> // do stuff
> OGR_G_DestroyGeometry(handle);
>
> As you can see, in one case, I have to pass in a pointer to the
> returned handle, and not just the handle. How can I accomplish this
> feat using a single type?
>
> I had
>
> data OGRGeometryH
> type Geometry = Ptr OGRGeometryH
Almost: Assuming that OGRGeometryH is some sort of pointer, e.g.
typedef struct OGRGeometry *OGRGeometryH
you could write:
> data OGRGeometry
> type OGRGeometryH = Ptr OGRGeometry
where OGRGeometryH is the type that you API exports.
> foreign import ccall
> oGR_G_CreateFromWkb :: ...whatever... -> Ptr OGRGeometryH -> OGRErr
Note that Ptr OGRGeometryH is in fact a pointer to a pointer, just as the
C type demands. When calling such a procedure you must first allocate
space. This is most elegantly done using alloca (I have added some basic
error handling, otherwise the value returned might be undefined):
> createFromWbk :: ...argtypes... -> Either OGRErr OGRGeometryH
> createFromWbk ...args... = alloca $ \ptr -> do
> -- in this code block you can peek and poke the ptr;
> -- space will be deallocated after block exits
> res <- oGR_G_CreateFromWkb ...args... ptr
> if checkResultOK res
> then do
> -- this can be shortened to: liftM Right $ peek ptr
> -- or: peek ptr >>= return . Right
> h <- peek ptr
> return (Right h)
> else return (Left res)
(Instead of returning an Either type you could throw exceptions, but you
didn't ask about error handling, did you ?-)
Cheers
Ben
More information about the Haskell-Cafe
mailing list