Class: Fiddle::CStructEntity
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
| 
         Subclasses: 
        
       | 
    |
| Super Chains via Extension / Inclusion / Inheritance | |
| 
         Class Chain: 
        
          self,
           
      Pointer
         | 
    |
| 
         Instance Chain: 
        
       | 
    |
| Inherits: | 
        Fiddle::Pointer
        
  | 
    
| Defined in: | ext/fiddle/lib/fiddle/struct.rb | 
Overview
A pointer to a C structure
Constant Summary
Class Method Summary
- .alignment(types)
 - 
    
      .malloc(types, func = nil, size = size(types), &block)  
    
    
Allocates a C struct with the
typesprovided. - 
    
      .new(addr, types, func = nil)  ⇒ CStructEntity 
    
    constructor
    
Wraps the C pointer
addras a C struct with the giventypes. - 
    
      .size(types)  
    
    
Returns the offset for the packed sizes for the given
types. 
Pointer - Inherited
| .[] | Get the underlying pointer for ruby object   | 
    
| .new | Create a new pointer to   | 
    
| .read | Or read the memory at address   | 
    
| .to_ptr | Alias for Pointer.[].  | 
    
| .write | Write bytes in   | 
    
Instance Attribute Summary
Pointer - Inherited
| #free | Get the free function for this pointer.  | 
    
| #free= | Set the free function for this pointer to   | 
    
| #freed? | Returns if the free function for this pointer has been called.  | 
    
| #null? | Returns   | 
    
| #size | Get the size of this pointer.  | 
    
| #size= | Set the size of this pointer to .size  | 
    
Instance Method Summary
- 
    
      #[](*args)  
    
    
Fetch struct member
nameif only one argument is specified. - 
    
      #[]=(*args)  
    
    
Set struct member
name, to valueval. - 
    
      #assign_names(members)  
    
    
Set the names of the
membersin this C struct. - 
    
      #set_ctypes(types)  
    
    
Calculates the offsets and sizes for the given
typesin the struct. - #to_s Internal use only
 
ValueUtil - Included
PackInfo - Included
Pointer - Inherited
| #+ | Returns a new pointer instance that has been advanced   | 
    
| #+@ | Returns a new   | 
    
| #- | Returns a new pointer instance that has been moved back   | 
    
| #-@ | Returns a new   | 
    
| #<=> | Returns -1 if less than, 0 if equal to, 1 if greater than   | 
    
| #== | Returns true if   | 
    
| #[] | Returns integer stored at index.  | 
    
| #[]= | Set the value at   | 
    
| #call_free | Call the free function for this pointer.  | 
    
| #eql? | Alias for Pointer#==.  | 
    
| #inspect | Returns a string formatted with an easily readable representation of the internal state of the pointer.  | 
    
| #ptr | Alias for Pointer#+@.  | 
    
| #ref | Alias for Pointer#-@.  | 
    
| #to_i | Returns the integer memory location of this pointer.  | 
    
| #to_int | Alias for Pointer#to_i.  | 
    
| #to_s | Returns the pointer contents as a string.  | 
    
| #to_str | Returns the pointer contents as a string.  | 
    
| #to_value | Cast this pointer to a ruby object.  | 
    
Constructor Details
    .new(addr, types, func = nil)  ⇒ CStructEntity 
  
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 Pointer.new
# File 'ext/fiddle/lib/fiddle/struct.rb', line 340
def initialize(addr, types, func = nil) if func && addr.is_a?(Pointer) && addr.free raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?' end set_ctypes(types) super(addr, @size, func) end
Class Method Details
.alignment(types)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/struct.rb', line 277
def CStructEntity.alignment(types) max = 1 types.each do |type, count = 1| if type.respond_to?(:entity_class) n = type.alignment else n = ALIGN_MAP[type] end max = n if n > max end max end
.malloc(types, func = nil, size = size(types), &block)
Allocates a C struct with the types provided.
See Fiddle::Pointer.malloc for memory management issues.
# File 'ext/fiddle/lib/fiddle/struct.rb', line 293
def CStructEntity.malloc(types, func = nil, size = size(types), &block) if block_given? super(size, func) do |struct| struct.set_ctypes types yield struct end else struct = super(size, func) struct.set_ctypes types struct end end
.size(types)
# File 'ext/fiddle/lib/fiddle/struct.rb', line 313
def CStructEntity.size(types) offset = 0 max_align = types.map { |type, count = 1| last_offset = offset if type.respond_to?(:entity_class) align = type.alignment type_size = type.size else align = PackInfo::ALIGN_MAP[type] type_size = PackInfo::SIZE_MAP[type] end offset = PackInfo.align(last_offset, align) + (type_size * count) align }.max PackInfo.align(offset, max_align) end
Instance Method Details
#[](*args)
Fetch struct member name if only one argument is specified. If two arguments are specified, the first is an offset and the second is a length and this method returns the string of length bytes beginning at offset.
Examples:
my_struct = struct(['int id']).malloc
my_struct.id = 1
my_struct['id'] # => 1
my_struct[0, 4] # => "\x01\x00\x00\x00".b
  # File 'ext/fiddle/lib/fiddle/struct.rb', line 413
def [](*args) return super(*args) if args.size > 1 name = args[0] idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] if( ty.is_a?(Array) ) if ty.first.respond_to?(:entity_class) return @nested_structs[name] else r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) end elsif ty.respond_to?(:entity_class) return @nested_structs[name] 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 StructArray.new(self + @offset[idx], ty[0], val) else return val end end
#[]=(*args)
Set struct member name, to value val. If more arguments are specified, writes the string of bytes to the memory at the given offset and length.
Examples:
my_struct = struct(['int id']).malloc
my_struct['id'] = 1
my_struct[0, 4] = "\x01\x00\x00\x00".b
my_struct.id # => 1
  # File 'ext/fiddle/lib/fiddle/struct.rb', line 465
def []=(*args) return super(*args) if args.size > 2 name, val = *args name = name.to_s if name.is_a?(Symbol) nested_struct = @nested_structs[name] if nested_struct if nested_struct.is_a?(StructArray) if val.nil? nested_struct.each do |s| s.replace(nil) end else val.each_with_index do |v, i| nested_struct[i] = v end end else nested_struct.replace(val) end return val end 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)
Set the names of the members in this C struct
# File 'ext/fiddle/lib/fiddle/struct.rb', line 349
def assign_names(members) @members = [] @nested_structs = {} members.each_with_index do |member, index| if member.is_a?(Array) # nested struct member_name = member[0] struct_type, struct_count = @ctypes[index] if struct_count.nil? struct = struct_type.new(to_i + @offset[index]) else structs = struct_count.times.map do |i| struct_type.new(to_i + @offset[index] + i * struct_type.size) end struct = StructArray.new(to_i + @offset[index], struct_type, structs) end @nested_structs[member_name] = struct else member_name = member end @members << member_name end end
#set_ctypes(types)
Calculates the offsets and sizes for the given types in the struct.
# File 'ext/fiddle/lib/fiddle/struct.rb', line 375
def set_ctypes(types) @ctypes = types @offset = [] offset = 0 max_align = types.map { |type, count = 1| orig_offset = offset if type.respond_to?(:entity_class) align = type.alignment type_size = type.size else align = ALIGN_MAP[type] type_size = SIZE_MAP[type] end offset = PackInfo.align(orig_offset, align) @offset << offset offset += (type_size * count) align }.max @size = PackInfo.align(offset, max_align) end
#to_s
# File 'ext/fiddle/lib/fiddle/struct.rb', line 505
def to_s() # :nodoc: super(@size) end