類別 Fiddle::CStructEntity
指向 C 結構的指標
公開類別方法
alignment(types) 按一下以切換來源
# File 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)) { |struct| ... } 按一下以切換來源
配置具有提供的 types
的 C 結構。
請參閱 Fiddle::Pointer.malloc
以了解記憶體管理問題。
呼叫超類別方法
Fiddle::Pointer::malloc
# File 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
new(addr, types, func = nil) 按一下以切換來源
將 C 指標 addr
包裝為具有給定 types
的 C 結構。
當執行個體被垃圾回收時,會呼叫 C 函式 func
。
另請參閱 Fiddle::Pointer.new
呼叫超類別方法
Fiddle::Pointer::new
# File 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
size(types) 按一下以切換來源
傳回給定 types
的封裝大小的偏移量。
Fiddle::CStructEntity.size( [ Fiddle::TYPE_DOUBLE, Fiddle::TYPE_INT, Fiddle::TYPE_CHAR, Fiddle::TYPE_VOIDP ]) #=> 24
# File 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
公開執行個體方法
[](*args) 按一下以切換來源
如果只指定一個引數,則擷取結構成員 name
。如果指定兩個引數,第一個引數是偏移量,第二個引數是長度,而且此方法會傳回從 offset
開始的 length
位元組字串。
範例
my_struct = struct(['int id']).malloc my_struct.id = 1 my_struct['id'] # => 1 my_struct[0, 4] # => "\x01\x00\x00\x00".b
呼叫超類別方法
Fiddle::Pointer::[]
# File 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) 按一下以切換來源
設定結構成員 name
,為值 val
。如果指定更多引數,會將位元組字串寫入具有給定 offset
和 length
的記憶體。
範例
my_struct = struct(['int id']).malloc my_struct['id'] = 1 my_struct[0, 4] = "\x01\x00\x00\x00".b my_struct.id # => 1
呼叫超類別方法
Fiddle::Pointer#[]=
# File 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) 按一下以切換來源
設定此 C 結構中 members
的名稱
# File 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) 按一下以切換來源
計算結構中給定 types
的位移和大小。
# File 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