Assigning nested struct members in Ruby FFI
Consider the following two FFI structures:
class A < FFI::Struct
layout :data, :int
end
class B < FFI::Struct
layout :nested, A
end
To instantiate them:
a = A.new
b = B.new
Now when I try to assign a
to b.nested
like this:
b[:nested] = a
I am getting the following error:
ArgumentError: put not supported for FFI::StructByValue
FFI doesn't seem to allow assignment with the [] syntax if the nested structure is "nested by value", that is, it is not a pointer. If so, how do I then assign a
to b.nested
?
+3
source to share
1 answer
When you use FFI for a socket, it can work like this:
b = B.new
b[:nested][:data] = 42
b[:nested][:data] #=> 42
FFI object "b" created its own "a" object; you don't need to create your own.
It looks like you are trying to create your own "a" object and then store it:
a = A.new
b = B.new
b[:nested] = a #=> fails because "a" is a Ruby object, not a nested value
The solution is to store "a" as a pointer:
require 'ffi'
class A < FFI::Struct
layout :data, :int
end
class B < FFI::Struct
layout :nested, :pointer # we use a pointer, not a class
end
a = A.new
b = B.new
# Set some arbitrary data
a[:data] = 42
# Set :nested to the pointer to the "a" object
b[:nested] = a.pointer
# To prove it works, create a new object with the pointer
c = A.new(b[:nested])
# And prove we can get the arbitrary data
puts c[:data] #=> 42
+3
source to share