[ocaml-ctypes] Abstract 'a typ

Jeremy Yallop yallop at gmail.com
Tue Mar 10 14:34:36 GMT 2015

On 10 March 2015 at 12:10, Thomas Braibant <thomas.braibant at gmail.com> wrote:
> On Mon, Mar 9, 2015 at 10:37 PM, Daniel Bünzli
> <daniel.buenzli at erratique.ch> wrote:
>> If your bindings are thin you should just use an OCaml abstract type that denotes pointers to void pointers. The only place where you need to be careful is in the bindings themselves but that should be trivial.
>> For example in tsdl:
>> https://github.com/dbuenzli/tsdl/blob/bc18d14b1a28af99ebc30b61e303ee5304055d31/src/tsdl.mli#L727
>> https://github.com/dbuenzli/tsdl/blob/bc18d14b1a28af99ebc30b61e303ee5304055d31/src/tsdl.ml#L1093-L1095
> Thanks. This is what I had in mind with void pointers. I will go
> forward with that solution. (And refrain myself from trying to be
> pedantic inside these particular bindings.)

You can use the module system to distinguish different types of
pointers within your library.  For example:

   module Foo :
      type t
      val t : t typ
   end =
      type t = unit
      let t = void

Now 'ptr Foo.t' and 'ptr void' have the same representation but
different types, so you can't accidentally mix them up.

It's also possible to write something that corresponds quite closely
to your C definition:

   typedef struct foo foo;

There are two parts to this definition.  First, there's an incomplete
struct type "struct foo".  In ctypes you can create an incomplete
struct by calling Ctypes.structure without calling Ctypes.seal:

   let struct_foo = structure "foo"

Once again, you can use the module system to ensure that Ctypes.seal
is never called.

The other part of the definition is the typedef.  In trunk there's a
function Ctypes.typedef that's just a thin wrapper around a view,
changing only the printing behaviour:

  val typedef : 'a typ -> string -> 'a typ

Putting these together gives you the following:

  module Foo :
    type t
    val t : t typ
  end =
    type t = unit structure
    let t = typedef (structure "foo") "foo"

This has the following properties: (1) It's distinguished from other
incomplete/"abstract" types in the OCaml type system; (2) it has the
correct representation (i.e. as a structure type with no fields); (3)
it has the correct printing behaviour, e.g.:

  # ptr (ptr Foo.t);;
  - : Foo.t ptr ptr typ = foo**

The printing behaviour is useful for development and debugging, but
should also give you better types in generated stub code.

More information about the Ctypes mailing list