yallop / ocaml-ctypes

Library for binding to C libraries using pure OCaml
MIT License
369 stars 95 forks source link

Add support for unknown integer types. #652

Open yallop opened 4 years ago

yallop commented 4 years ago

Aims and background

This PR adds support for using integer types of unknown properties (size, alignment requirements, signedness).

For example, POSIX specifies that off_t is a signed integer type, but does not specify its size. And it specifies that dev_t is an integer type, but does not specify its size or signedness. This PR makes it possible to bind and use both types nonetheless.

Similarly, the C standard allows implementations to choose the properties of enum types. Implementations sometimes also include extensions (such as GCC's -fshort-enums) that allow users to vary those properties. That implementation freedom can make it difficult to use enums from ctypes (cf. #650). This PR makes it easier to bind and use such types in ctypes code.

Design

This PR adds two new functions, signed and unsigned, to the Ctypes.TYPE signature:

val signed  : string -> (module signed)
val unsigned : string -> (module unsigned)

Users can apply these functions in type-binding functions to bind integer types of unknown properties:

module Types(C: Ctypes.TYPE) =
struct
  open C

  let dev_t = signed "dev_t"
  let flags = unsigned "enum flags"
end

and unpack the bindings to build modules with information about those types:

module Dev_t = (val dev_t)
module Flags = (val flags)

The signatures for Dev_t and Flags include all the standard integer operations (from Signed.S or Unsigned.S) as well as a typ value that makes it possible to use the new types to create values, bind functions, etc.

module type signed = sig include Signed.S val t : t typ end
module type unsigned = sig include Unsigned.S val t : t typ end

Limitations

Since the type binding interface currently requires that functors such as Types above are applicative, it is not possible to unpack Dev_t and Flags inside the functor.

fdopen commented 4 years ago

It's similar to: https://fdopen.github.io/ppx_cstubs/opaque/#integers-of-unknown-size-and-signedness But I've added an explicit function for integers of unknown signedness, instead of implicit conversions from a signed type to an unsigned interface. I also use custom modules for int8/int16. Otherwise max_int is wrong and the overflow semantic might be surprising.