rubyfiddle

How to copy an instance of the Ruby Fiddle struct?


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.


Solution

  • 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