Open kojix2 opened 1 year ago
The method mentioned in the "Alternative" section using a binary string with pack
and unpack
is the method used in wasmtime-rb.
These are Memory#read(offset, size)
and Memory#write(offset, value)
. I think this is a very easy-to-use and highly versatile method. Therefore, it might be better to adopt this method rather than adding a new View.
I am a little unsure if the code below is completely correct, but it should work like this.
Write:
memory.write(
addr,
case type
when 'int8' then arg.pack('c*')
when 'uint8' then arg.pack('C*')
when 'int16' then arg.pack('s*')
when 'uint16' then arg.pack('S*')
when 'int32' then arg.pack('l*')
when 'uint32' then arg.pack('L*')
when 'int64' then arg.pack('q*')
when 'uint64' then arg.pack('Q*')
when 'float32' then arg.pack('e*')
when 'float64' then arg.pack('E*')
else raise "unsupported type: #{type}"
end
)
Read:
case type
when 'int8' then memory.read(addr, len * 1).unpack('c*')
when 'uint8' then memory.read(addr, len * 1).unpack('C*')
when 'int16' then memory.read(addr, len * 2).unpack('s*')
when 'uint16' then memory.read(addr, len * 2).unpack('S*')
when 'int32' then memory.read(addr, len * 4).unpack('l*')
when 'uint32' then memory.read(addr, len * 4).unpack('L*')
when 'int64' then memory.read(addr, len * 8).unpack('q*')
when 'uint64' then memory.read(addr, len * 8).unpack('Q*')
when 'float32' then memory.read(addr, len * 4).unpack('e*')
when 'float64' then memory.read(addr, len * 8).unpack('E*')
else raise "unsupported type: #{type}"
end
Of course, the same thing can be done with the current version of wasmer-ruby using uint8_view
.
Write:
uint8_view = memory.uint8_view(addr)
arg_uint8 = case type
when 'int8' then arg.pack('c*')
when 'uint8' then arg.pack('C*')
when 'int16' then arg.pack('s*')
when 'uint16' then arg.pack('S*')
when 'int32' then arg.pack('l*')
when 'uint32' then arg.pack('L*')
when 'int64' then arg.pack('q*')
when 'uint64' then arg.pack('Q*')
when 'float32' then arg.pack('e*')
when 'float64' then arg.pack('E*')
else raise "unsupported type: #{type}"
end.unpack('C*')
arg_uint8.each_with_index do |a, i|
uint8_view[i] = a
end
Read:
uint8_view = memory.uint8_view(addr)
case type
when 'int8' then Array.new(len * 1) { |i| uint8_view[i] }.pack('C*').unpack('c*')
when 'uint8' then Array.new(len * 1) { |i| uint8_view[i] }.pack('C*').unpack('C*')
when 'int16' then Array.new(len * 2) { |i| uint8_view[i] }.pack('C*').unpack('s*')
when 'uint16' then Array.new(len * 2) { |i| uint8_view[i] }.pack('C*').unpack('S*')
when 'int32' then Array.new(len * 4) { |i| uint8_view[i] }.pack('C*').unpack('l*')
when 'uint32' then Array.new(len * 4) { |i| uint8_view[i] }.pack('C*').unpack('L*')
when 'int64' then Array.new(len * 8) { |i| uint8_view[i] }.pack('C*').unpack('q*')
when 'uint64' then Array.new(len * 8) { |i| uint8_view[i] }.pack('C*').unpack('Q*')
when 'float32' then Array.new(len * 4) { |i| uint8_view[i] }.pack('C*').unpack('e*')
when 'float64' then Array.new(len * 8) { |i| uint8_view[i] }.pack('C*').unpack('E*')
else raise "unsupported type: #{type}"
end
Hi! Thank you for creating very useful library.
Motivation
I am building a tool as a hobby to call WebAssembly functions generated by Crystal language from Ruby to speed up. When I tried to pass a Ruby array to Wasm, I noticed that
int64_view
,uint64_view
,float32_view
, andfloat64_view
were not yet provided.Proposed solution
new methods:
uint64_view
,int64_view
,float32_view
, andfloat64_view
new classesUint64View
,Int64View
,Float32View
, andFloat64View
Alternatives
The use of binary strings is a possible alternative. In that case, Ruby methods such as
pack
andunpack
could be used.Additional context
You can find similar functionality in Python bindings. https://github.com/wasmerio/wasmer-python/commit/b4846547648d92b14f0a2f442c9fb4cf46d8efc7