The Binding Generator C->Haskell : Implementation of Haskell Binding Modules : Pointer Hooks
Previous: Set Hooks
Next: Class Hooks

2.10. Pointer Hooks

{#pointer [*] cid [as hsid] [foreign | stable] [newtype | -> hsid2] [nocode]#}

A pointer hook facilitates the mapping of C to Haskell pointer types. In particular, it enables the use of ForeignPtr and StablePtr types and defines type name translations for pointers to non-basic types. In general, such a hook establishes an association between the C type cid or *cid and the Haskell type hsid, where the latter defaults to cid if not explicitly given. The identifier cid will usually be a type name, but in the case of *cid may also be a struct, union, or enum tag. If both a type name and a tag of the same name are available, the type name takes precedence. Optionally, the Haskell representation of the pointer can be by a ForeignPtr or StablePtr instead of a plain Ptr. If the newtype tag is given, the Haskell type hsid is defined as a newtype rather than a transparent type synonym. In case of a newtype, the type argument to the Haskell pointer type will be hsid, which gives a cyclic definition, but the type argument is here really only used as a unique type tag. Without newtype, the default type argument is (), but another type can be specified after the symbol ->.

For example, we may have

{#pointer *GtkObject as Object newtype#}

This will generate a new type Object as follows:

newtype Object = Object (Ptr Object)

which enables exporting Object as an abstract type and facilitates type checking at call sites of imported functions using the encapsulated pointer. The latter is achieved by C->Haskell as follows. The tool remembers the association of the C type *GtkObject with the Haskell type Object, and so, it generates for the C function

void gtk_unref_object (GtkObject *obj);

the import declaration

foreign import gtk_unref_object :: Object -> IO ()

This function can obviously only be applied to pointers of the right type, and thus, protects against the common mistake of confusing the order of pointer arguments in function calls.

However, as the Haskell FFI does not permit to directly pass ForeignPtrs to function calls or return them, the tool will use the type Ptr HsName in this case, where HsName is the Haskell name of the type. So, if we modify the above declaration to be

{#pointer *GtkObject as Object foreign newtype#}

the type Ptr Object will be used instead of a plain Object in import declarations; i.e., the previous import declaration will become

foreign import gtk_unref_object :: Ptr Object -> IO ()

To simplify the required marshalling code for such pointers, the tool automatically generates a function

withObject :: Object -> (Ptr Object -> IO a) -> IO a

As an example that does not represent the pointer as an abstract type, consider the C type declaration:

typedef struct {int x, y;} *point;

We can represent it in Haskell as

data Point = Point {x :: Int, y :: Int}
{#pointer point as PointPtr -> Point#}

which will translate to

data Point = Point {x :: Int, y :: Int}
type PointPtr = Ptr Point

and establish a type association between point and PointPtr.

If the keyword nocode is added to the end of a pointer hook, C->Haskell will not emit a type declaration. This is useful when a C->Haskell module wants to make use of an existing type declaration in a binding not generated by C->Haskell (i.e., where there are no .chi files).

Restriction: The name cid cannot be a basic C type (such as int), it must be a defined name.


The Binding Generator C->Haskell : Implementation of Haskell Binding Modules : Pointer Hooks
Previous: Set Hooks
Next: Class Hooks