ppx_cstubs provides various helper to deal with values whose types differ from platform to platform or that are kept opaque.
let%c myabstract = abstract "foo"
The statement above will be translated to something along the following lines - with
alignment determined automatically:
type myabstract let myabstract : myabstract Ctypes.abstract Ctypes.typ = Ctypes.abstract ~size ~alignment ~name:"foo"
abstract is most suitable for structs and unions, whose members are private or don’t need to be accessed from OCaml.
abstract guarantees an uniform representation of the values inside the OCaml heap and functions like Ctypes.addr can be applied to its values.
let%c myopaque = opaque "foo" (* 'myopaque' will be of type 'myopaque Ctypes.typ' *)
opaque is similar to
abstract, but will choose the best memory representation available for the type. If
foo turns out to be an integer type, it will be an integer inside OCaml. If it is a pointer, it will be of type
Ctypes.ptr - or
opaque is preferable to
abstract, if values of the corresponding type are usually passed by value.
module Signed_t = [%c int "foo"] module Unsigned_t = [%c uint "foo"] module Unknown_signed = [%c aint "foo"] external foo : Signed_t.t -> void let f t = Signed.add (Signed_t.of_int (-42)) t
module Signed_t = [%c int "foo"] creates an module
Signed_t with the signature of Signed.S, and also include an additional value
t of type
t Ctypes.typ that can be used inside
[%c uint "foo"] will create an analogous module with a signature of Unsigned.S.
[%c aint "foo"] will also be of type
Unsigned.S, but with an additional value
min_int that can be used to easily determine, if the type is signed or not.
[%c int "foo"] and
[%c uint "foo"] will throw an error during preprocessing, if the underlying type differs in signedness.
Integer types larger than 8 bytes are not supported.