1
0
Fork 0
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:
sinisterchipmunk 2020-01-22 20:37:23 -05:00 committed by Nobuyoshi Nakada
parent 4a835621ce
commit 77cc13943c
Notes: git 2020-05-23 14:29:42 +09:00
2 changed files with 42 additions and 1 deletions

View file

@ -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

View file

@ -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]