# class Fiddle::CStructEntity

A C struct wrapper

### Public Class Methods

malloc(types, func = nil) click to toggle source

Allocates a C struct with the `types` provided.

When the instance is garbage collected, the C function `func` is called.

    # File ext/fiddle/lib/fiddle/struct.rb, line 86
    def CStructEntity.malloc(types, func = nil)
      addr = Fiddle.malloc(CStructEntity.size(types))
      CStructEntity.new(addr, types, func)
    end

new(addr, types, func = nil) click to toggle source

Wraps the C pointer `addr` as a C struct with the given `types`.

When the instance is garbage collected, the C function `func` is called.

See also Fiddle::Pointer.new

Calls superclass method Fiddle::Pointer.new

    # File ext/fiddle/lib/fiddle/struct.rb, line 119
    def initialize(addr, types, func = nil)
      set_ctypes(types)
      super(addr, @size, func)
    end

size(types) click to toggle source

Returns the offset for the packed sizes for the given `types`.

    Fiddle::CStructEntity.size(
      [ Fiddle::TYPE_DOUBLE,
        Fiddle::TYPE_INT,
        Fiddle::TYPE_CHAR,
        Fiddle::TYPE_VOIDP ]) #=> 24

    # File ext/fiddle/lib/fiddle/struct.rb, line 98
    def CStructEntity.size(types)
      offset = 0

      max_align = types.map { |type, count = 1|
        last_offset = offset

        align = PackInfo::ALIGN_MAP[type]
        offset = PackInfo.align(last_offset, align) +
                 (PackInfo::SIZE_MAP[type] * count)

        align
      }.max

      PackInfo.align(offset, max_align)
    end

### Public Instance Methods

[](name) click to toggle source

Fetch struct member `name`

Calls superclass method Fiddle::Pointer.[]

    # File ext/fiddle/lib/fiddle/struct.rb, line 151
    def [](name)
      idx = @members.index(name)
      if( idx.nil? )
        raise(ArgumentError, "no such member: #{name}")
      end
      ty = @ctypes[idx]
      if( ty.is_a?(Array) )
        r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
      else
        r = super(@offset[idx], SIZE_MAP[ty.abs])
      end
      packer = Packer.new([ty])
      val = packer.unpack([r])
      case ty
      when Array
        case ty[0]
        when TYPE_VOIDP
          val = val.collect{|v| Pointer.new(v)}
        end
      when TYPE_VOIDP
        val = Pointer.new(val[0])
      else
        val = val[0]
      end
      if( ty.is_a?(Integer) && (ty < 0) )
        return unsigned_value(val, ty)
      elsif( ty.is_a?(Array) && (ty[0] < 0) )
        return val.collect{|v| unsigned_value(v,ty[0])}
      else
        return val
      end
    end

[]=(name, val) click to toggle source

Set struct member `name`, to value `val`

Calls superclass method Fiddle::Pointer#[]=

    # File ext/fiddle/lib/fiddle/struct.rb, line 185
    def []=(name, val)
      idx = @members.index(name)
      if( idx.nil? )
        raise(ArgumentError, "no such member: #{name}")
      end
      ty  = @ctypes[idx]
      packer = Packer.new([ty])
      val = wrap_arg(val, ty, [])
      buff = packer.pack([val].flatten())
      super(@offset[idx], buff.size, buff)
      if( ty.is_a?(Integer) && (ty < 0) )
        return unsigned_value(val, ty)
      elsif( ty.is_a?(Array) && (ty[0] < 0) )
        return val.collect{|v| unsigned_value(v,ty[0])}
      else
        return val
      end
    end

assign_names(members) click to toggle source

Set the names of the `members` in this C struct

    # File ext/fiddle/lib/fiddle/struct.rb, line 125
    def assign_names(members)
      @members = members
    end

set_ctypes(types) click to toggle source

Calculates the offsets and sizes for the given `types` in the struct.

    # File ext/fiddle/lib/fiddle/struct.rb, line 130
    def set_ctypes(types)
      @ctypes = types
      @offset = []
      offset = 0

      max_align = types.map { |type, count = 1|
        orig_offset = offset
        align = ALIGN_MAP[type]
        offset = PackInfo.align(orig_offset, align)

        @offset << offset

        offset += (SIZE_MAP[type] * count)

        align
      }.max

      @size = PackInfo.align(offset, max_align)
    end