Is there some way to deterministically interoperate bit fields?

For a structure like

struct A {
    int sync:1;
    int data:31;
};

is there a way to deterministically create interoperable code?

This is kind of a simple example still, because I’d also like to be able to interoperate with code that’s written like this where there are a bunch of uint8 boolx:1 (let’s say 5 of them), then some other fields, and then a few more uint8 boolx:1 again. How can I write interop bindings for them with Odin?

I believe C bit fields are not standardised but I also believe most of the compilers implement them reasonably like Odin does. That being said this should be equivalent:

A :: bit_field i32 {
    sync: bool | 1,
    data: i32  | 31,
}

C bit-fields have been standard since C99 at least. See §6.7.7.6 in C99 or §6.7.8.6 in C11 and C17.

The way they work in C code, yes. The way they’re laid out in memory is entirely implementation-defined, though–and that’s what’s relevant for binding it.

1 Like

alright thanks

what about structs that contain a few fields in between?

something like

struct SomeInternalType { /* ... */ };

struct A {
    uint8_t flagA: 1;
    uint8_t flagB: 1;
    SomeInternalType x;
    uint8_t flagC: 1;
}

Would those three flags be automatically packed together? Or whether flagC will be treated like a separate uint8_t altogether?

Odin does not reorder struct members. That last bit will not be packed with the others.

For Odin, it would have to look something like this:

A :: struct {
    using flags0: bit_field u8 { 
        flagA: u8 | 1,
        flagB: u8 | 1,
    },
    x: SomeInternalType,
    using flags1: bit_field u8 {
        flagC: u8 | 1,
    },
}

But you will see a warning when you do this as it suggests you should use a bit_set instead if all of the flags are 1-bit in size, because bit_set is for FLAGS specifically.