mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/fiddle] Fix assignment to array within struct (#26)
* Allow access to a struct's underlying memory with `struct[offset, length]`. https://github.com/ruby/fiddle/commit/24083690a6
This commit is contained in:
parent
4a835621ce
commit
77cc13943c
Notes:
git
2020-05-23 14:29:42 +09:00
2 changed files with 42 additions and 1 deletions
|
@ -20,6 +20,33 @@ module Fiddle
|
|||
end
|
||||
end
|
||||
|
||||
# Wrapper for arrays within a struct
|
||||
class StructArray < Array
|
||||
include ValueUtil
|
||||
|
||||
def initialize(ptr, type, initial_values)
|
||||
@ptr = ptr
|
||||
@type = type
|
||||
@align = PackInfo::ALIGN_MAP[type]
|
||||
@size = Fiddle::PackInfo::SIZE_MAP[type]
|
||||
@pack_format = Fiddle::PackInfo::PACK_MAP[type]
|
||||
super(initial_values.collect { |v| unsigned_value(v, type) })
|
||||
end
|
||||
|
||||
def to_ptr
|
||||
@ptr
|
||||
end
|
||||
|
||||
def []=(index, value)
|
||||
if index < 0 || index >= size
|
||||
raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size]
|
||||
end
|
||||
|
||||
to_ptr[index * @size, @size] = [value].pack(@pack_format)
|
||||
super(index, value)
|
||||
end
|
||||
end
|
||||
|
||||
# Used to construct C classes (CUnion, CStruct, etc)
|
||||
#
|
||||
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
|
||||
|
@ -191,7 +218,7 @@ module Fiddle
|
|||
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])}
|
||||
return StructArray.new(self + @offset[idx], ty[0], val)
|
||||
else
|
||||
return val
|
||||
end
|
||||
|
|
|
@ -129,6 +129,20 @@ module Fiddle
|
|||
assert_equal([0,1,2], ary.value)
|
||||
end
|
||||
|
||||
def test_struct_array_assignment()
|
||||
instance = Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc
|
||||
instance.stages[0] = 1024
|
||||
instance.stages[1] = 10
|
||||
instance.stages[2] = 100
|
||||
assert_equal 1024, instance.stages[0]
|
||||
assert_equal 10, instance.stages[1]
|
||||
assert_equal 100, instance.stages[2]
|
||||
assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3),
|
||||
instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT]
|
||||
assert_raise(IndexError) { instance.stages[-1] = 5 }
|
||||
assert_raise(IndexError) { instance.stages[3] = 5 }
|
||||
end
|
||||
|
||||
def test_struct()
|
||||
s = LIBC::MyStruct.malloc()
|
||||
s.num = [0,1,2,3,4]
|
||||
|
|
Loading…
Reference in a new issue