1

It's not obvious how to copy an instance of the Fiddle struct. I found an ugly solution using the Fiddle::Pointer like this.

require 'fiddle/import'

X = Fiddle::Importer.struct [
  'int a',
  'int b',
]

x = X.malloc
x.a = 1
x.b = 2

x2 = X.malloc
Fiddle::Pointer.new(x2.to_i)[0, X.size] = x.to_ptr.to_s
x2.b = 3
p [x.b, x2.b]

Is there a better way of doing this? One other way I thought of was using the []= operator of the super class(Fiddle::Pointer) of the x2.to_ptr, but it was worse than the above solution.

relent95
  • 3,703
  • 1
  • 14
  • 17

1 Answers1

1

The class returned by Fiddle::Importer.struct implements [] and []= to retrieve and set the struct members by name:

x['a'] #=> 1
x['b'] #=> 2

However, when called with 2 arguments, these methods behave like their Fiddle::Pointer counterparts and get / set the raw binary data:

x[0, 4] #=> "\x01\x00\x00\x00"   <- a's binary data
x[4, 4] #=> "\x02\x00\x00\x00"   <- b's binary data

x[4, 4] = [-5].pack('l') #=> "\xFB\xFF\xFF\xFF"
x.b #=> -5

To copy x's entire data to x2:

x2[0, X.size] = x[0, X.size]

x2.a #=> 1
x2.b #=> 2
Stefan
  • 109,145
  • 14
  • 143
  • 218
  • 1
    Thanks. I tried this before but failed because I was using Ruby 2.7. In Ruby 3.2, it works fine. I confirmed this feature was added in Ruby 3.0.0. It would be great if you mention this for future readers. – relent95 Jul 07 '23 at 01:50