ocaml-ctypes
ocaml-ctypes copied to clipboard
Add support for unknown integer types.
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.
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.