How to use a structure with variable length array or bit field in Ruby-FFI

https://github.com/ffi/ffi/issues/874

Use a struct with a variable length array in Ruby-FFI. Or how to use bitfields.

When I consulted on the official Github issue, the developer taught me how to do it, so I will keep it as a record.

Hello Ruby-FFI developers!

Thank you for your wonderful work.

I have a question. How do I convert the structure of a variable length array into Ruby code?

typedef struct {
	uint32_t capacity;
	int32_t dp_score, dp_max, dp_max2;
	uint32_t n_ambi:30, trans_strand:2;
	uint32_t n_cigar;
	uint32_t cigar[]; # Here
} mm_extra_t;

I have another question. I checked the ruby-ffi wiki and it says that bitfields are not supported. Is this still true today?

Answer by Lars Kanis

Bit fields are not supported, but can be emulated with simple integer arithmetic. Variable length arrays can be used in struct.pointers. Use it as follows:

class MmExtra < FFI::Struct
  layout capacity: :uint32,
    dp_score: :int32,
    dp_max: :int32,
    dp_max2: :int32,
    n_ambi_trans_strand: :uint32,
    n_cigar: :uint32
end

n_ambi = 123456
trans_strand = 0x2
cigar = [4,5,6]
s = MmExtra.new(FFI::MemoryPointer.new(MmExtra.size + FFI.type_size(:uint32) * cigar.size))
s[:n_ambi_trans_strand] = n_ambi | (trans_strand << 30)


s[:n_cigar] = cigar.size
s.pointer.put_array_of_uint32(s.size, cigar)

p n_ambi: s[:n_ambi_trans_strand] & ((1 << 30) - 1), trans_strand: (s[:n_ambi_trans_strand] >> 30) & ((1 << 2) - 1) # => {:n_ambi=>123456, :trans_strand=>2}
p s[:n_cigar]  # => 3
p s.pointer.get_array_of_uint32(s.size, 3) # => [4, 5, 6]
p s.pointer.read_bytes(s.pointer.size) # => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xE2\x01\x80\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00"

You can also add custom methods to MmExtra to access fields and perform bitfield operations.

Thank you.

Recommended Posts

How to use a structure with variable length array or bit field in Ruby-FFI
[Java] How to search for a value in an array (or list) with the contains method
How to use an array for a TreeMap key
How to use Z3 library in Scala with Eclipse
[How to insert a video in haml with Rails]
How to use JDD library in Scala with Eclipse
How to convert A to a and a to A using AND and OR in Java
How to query Array in jsonb with Rails + postgres
How to divide a two-dimensional array into four with ruby
How to use a foreign key with FactoryBot ~ Another solution
How to change a string in an array to a number in Ruby
How to create a placeholder part to use in the IN clause
Learning Ruby with AtCoder 13 How to make a two-dimensional array
How to add the same Indexes in a nested array
Mapping to a class with a value object in How to MyBatis
How to set up a proxy with authentication in Feign
[Ruby] How to count even or odd numbers in an array
How to make a jar file with no dependencies in Maven
[Ruby] I want to put an array in a variable. I want to convert to an array
How to use mssql-tools with alpine
How to use InjectorHolder in OpenAM
How to run a job with docker login in AWS batch
How to rename a model with foreign key constraints in Rails
How to use classes in Java?
How to store the information entered in textarea in a variable in the method
How to make a Java array
[Personal memo] How to interact with a random number generator in Java
How to develop from VScode in a remote destination environment or a remote destination container environment
[Rails] How to log in with a name by adding a devise name column
How to test private methods with arrays or variadic arguments in JUnit
How to change the value of a variable at a breakpoint in intelliJ
I want to ForEach an array with a Lambda expression in Java
[Java] [For beginners] How to insert elements directly in a 2D array
How to start a Docker container with a volume mounted in a batch file
A memorandum on how to use Eclipse
Multilingual Locale in Java How to use Locale
How to use custom helpers in rails
How to use named volume in docker-compose.yml
How to use BootStrap with Play Framework
[Rails] How to use rails console with docker
How to insert a video in Rails
How to add a new hash / array
How to use Docker in VSCode DevContainer
How to use MySQL in Rails tutorial
Notation to put a variable in a string
How to use environment variables in RubyOnRails
How to publish a library in jCenter
Understand in 5 minutes !! How to use Docker
How to use credentials.yml.enc introduced in Rails 5.2
How to use ExpandableListView in Android Studio
[Ruby] Learn how to use odd? Even? And count the even and odd numbers in the array!
How to get the ID of a user authenticated with Firebase in Swift
How to check if an instance variable is defined in a Ruby class
How to make a judgment method to search for an arbitrary character in an array
How to store data simultaneously in a model associated with a nested form (Rails 6.0.0)
How to use Eclipse on my PC with 32bit and 2GB of memory
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to display a web page in Java
How to use built-in h2db with spring boot
How to use an array for HashMap keys
How to use "sign_in" in integration test (RSpec)