How to deal with pointers to pointers in the FFI

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 but then can I declare that a function returns a Ptr (Geometry) ? -- I try to take things like a crow; war and chaos don't always ruin a picnic, they just mean you have to be careful what you swallow. -- Jessica Edwards

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 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)
Are these Ogre3D functions? If so, I hope you are planning on releasing these bindings! But I don't have an answer to your question, sorry. :\ - - Jake -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkj45dwACgkQye5hVyvIUKmRoQCfTOnlxfRCUY/9SY9qA29NNIJL AvYAn1m6h8b36amu+DBqd/r1dT5iXb/H =Smjr -----END PGP SIGNATURE-----

Sadly, nothing so awesome... OGR is part of GDAL, an open-source
geographic information system suite.
On Fri, Oct 17, 2008 at 3:22 PM, Jake McArthur
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
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)
Are these Ogre3D functions? If so, I hope you are planning on releasing these bindings!
But I don't have an answer to your question, sorry. :\
- - Jake -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkj45dwACgkQye5hVyvIUKmRoQCfTOnlxfRCUY/9SY9qA29NNIJL AvYAn1m6h8b36amu+DBqd/r1dT5iXb/H =Smjr -----END PGP SIGNATURE-----
-- I try to take things like a crow; war and chaos don't always ruin a picnic, they just mean you have to be careful what you swallow. -- Jessica Edwards

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jefferson Heard wrote:
Sadly, nothing so awesome... OGR is part of GDAL, an open-source geographic information system suite.
On Fri, Oct 17, 2008 at 3:22 PM, Jake McArthur
wrote: Are these Ogre3D functions? If so, I hope you are planning on releasing these bindings!
Aw. As I understand it, there is no plain C interface to Ogre3D right now, so I was wondering where these were coming from anyway. Oh well, I can dream. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkj46lIACgkQye5hVyvIUKlHGQCg0gE5QmoB51ZwGZ8i/dMgR1nJ ny8An3HrwdoKQkS2jLoGf0KooFsOuaEz =4kC8 -----END PGP SIGNATURE-----

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
participants (3)
-
Ben Franksen
-
Jake McArthur
-
Jefferson Heard