struct

A struct declaration inside a lib declares a C struct.

  1. lib C
  2. # In C:
  3. #
  4. # struct TimeZone {
  5. # int minutes_west;
  6. # int dst_time;
  7. # };
  8. struct TimeZone
  9. minutes_west : Int32
  10. dst_time : Int32
  11. end
  12. end

You can also specify many fields of the same type:

  1. lib C
  2. struct TimeZone
  3. minutes_west, dst_time : Int32
  4. end
  5. end

Recursive structs work just like you expect them to:

  1. lib C
  2. struct LinkedListNode
  3. prev, _next : LinkedListNode*
  4. end
  5. struct LinkedList
  6. head : LinkedListNode*
  7. end
  8. end

To create an instance of a struct use new:

  1. tz = C::TimeZone.new

This allocates the struct on the stack.

A C struct 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. tz = uninitialized C::TimeZone
  2. tz.minutes_west # => some garbage value

You can set and get its properties:

  1. tz = C::TimeZone.new
  2. tz.minutes_west = 1
  3. tz.minutes_west # => 1

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

You can also initialize some fields with a syntax similar to named arguments:

  1. tz = C::TimeZone.new minutes_west: 1, dst_time: 2
  2. tz.minutes_west # => 1
  3. tz.dst_time # => 2

A C struct 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(tz)
  2. tz.minutes_west = 1
  3. end
  4. tz = C::TimeZone.new
  5. change_it tz
  6. tz.minutes_west # => 0

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