union

A union declaration inside a lib declares a C union:

  1. lib U
  2. # In C:
  3. #
  4. # union IntOrFloat {
  5. # int some_int;
  6. # double some_float;
  7. # };
  8. union IntOrFloat
  9. some_int : Int32
  10. some_float : Float64
  11. end
  12. end

To create an instance of a union use new:

  1. value = U::IntOrFloat.new

This allocates the union on the stack.

A C union starts with all its fields set to “zero”: integers and floats start at zero, pointers start with an address of zero, etc.

To avoid this initialization you can use uninitialized:

  1. value = uninitialized U::IntOrFloat
  2. value.some_int # => some garbage value

You can set and get its properties:

  1. value = U::IntOrFloat.new
  2. value.some_int = 1
  3. value.some_int # => 1
  4. value.some_float # => 4.94066e-324

If the assigned value is not exactly the same as the property’s type, to_unsafe will be tried.

A C union is passed by value (as a copy) to functions and methods, and also passed by value when it is returned from a method:

  1. def change_it(value)
  2. value.some_int = 1
  3. end
  4. value = U::IntOrFloat.new
  5. change_it value
  6. value.some_int # => 0

Refer to the type grammar for the notation used in union field types.