Nim: How to wrap a c struct that contains bitfields?

345 views Asked by At

The question is if I see a bitfield in a c struct as such:

struct Example
{
    int A;
    int B;
    int C : 3;
    int D : 3;
    int E : 3;
    int F : 8;
    bool G : 1;
    bool H : 1;
};

Would the correct binding in Nim be as such?

type Example {.packed, importc: "Example", "example.h".} = object
  a {.importc: "a".} : int32
  b {.importc: "b".} : int32
  c {.bitsize: 3, importc: "c".} : int32
  d {.bitsize: 3, importc: "d".} : int32
  e {.bitsize: 3, importc: "e".} : int32
  f {.bitsize: 8, importc: "f".} : int32
  g {.bitsize: 1, importc: "g".} : bool
  h {.bitsize: 1, importc: "h".} : bool

or as such?

type Example {.importc: "Example", "example.h".} = object
  a {.importc: "a".} : int32
  b {.importc: "b".} : int32
  c {.importc: "c".} : int32
  d {.importc: "d".} : int32
  e {.importc: "e".} : int32
  f {.importc: "f".} : int32
  g {.importc: "g".} : bool
  h {.importc: "h".} : bool

Does the {.packed.} pragma align on the byte? Is the {.packed.} pragma even required here because I am importing from C?

1

There are 1 answers

0
shirleyquirk On BEST ANSWER

The correctest binding is:

type Example {.importc: "struct Example",header:"example.h".} = object
  A: cint
  B: cint
  C{.bitsize:3.}: cint
  D{.bitsize:3.}: cint
  E{.bitsize:3.}: cint
  F{.bitsize:8.}: cint
  G{.bitsize:1.}: bool
  H{.bitsize:1.}: bool

note struct Example because you said it was a C struct. If you intend to compile with nim cpp you can use the above, importc:"Example" or just importc with no argument

and yes, if you know your target machine's ints are 32bits, int32 is much more convenient and is what i would use.

{.packed.} is not what you want, it is the equivalent of

struct __attribute__((__packed__)) Example {
  ...
}

and using it results in a struct that is 11 bytes instead of 12

you don't need to individually {.importc.} each member, unless you want to change its name, i.e.

type Example{.importc:"struct Example",header:"example.h".} = object
  a{.importc:"A".}: cint
  b{.importc:"B".}: cint
  c{.importc:"C",bitsize:3.}: cint
  ...