Hi,
I’m working with OCaml’s ctypes
to bind to a C library using cstubs
, and I’ve run into a common pattern in C code: enums that are not declared as enum
types, but are instead stored as raw uint8_t
values in structs.
For example:
struct example {
uint32_t foo;
uint8_t mode;
};
The mode
field is meant to represent a specific set of values (like an enum), but it’s specified as a uint8_t
. For example, the enum could look like this:
enum spng_crc_action {
A = 0,
B = 1,
C = 2
};
In OCaml, I’d like to map this to a variant type.
Is the idiomatic way to handle this to use a Ctypes.view
over uint8_t
, mapping between the integer values and OCaml variants?
Something like (ignore the missing Unsigned.Uint8
usage):
type mode = A | B | C
let to_uint8 = function
| A -> 0
| B -> 1
| C -> 2
let of_uint8 = function
| 0 -> A
| 1 -> B
| 2 -> C
| _ -> invalid_arg "Unknown mode value"
let mode_view = view ~read:of_uint8 ~write:to_uint8 uint8_t
Then used in a struct field as:
let mode = Ctypes.field example "mode" mode_view
Is this the right approach? Or is there a better way to model these kinds of enums that are stored as fixed-size integers? Apologies if I got something wrong, I’m not very experienced with C.
Side note: I also tried using enum
for this, but it didn’t seem to work correctly — possibly because the backing type is uint8_t
. Happy to hear if that can be made to work too.
Thanks in advance!