Nested structures in Ruby Fiddle

1.3k Views Asked by At
  • Is it somehow possible to define nested structure signatures in Ruby's Fiddle lib?
  • Or at this point via any other up-to-date library which I'm not familiar with?

It is kind of a desperate question since I've searched through the documentation and Fiddle's code and found no clue about nested structs (although the FFI library was able to do that apparently and Fiddle should be a wrapper for FFI).

1

There are 1 best solutions below

0
On

How about:

data.c

#include <stdio.h>

struct A
{
    int a_id;
};

struct B
{
    int b_id;
    struct A a_nested;
};

void dump_b(struct B* b) {
    printf("B.b_id: %d\n", b->b_id);
    printf("B.a_nested.a_id: %d\n", b->a_nested.a_id);
}

fiddle.rb

# frozen_string_literal: true

require 'fiddle'
require 'fiddle/import'

module Test
  extend Fiddle::Importer

  dlload './data.dylib'

  B = struct [
    "int id",
    "int a_id"
  ]

  extern 'void dump_b(struct B*)'
end

b = Test::B.malloc

b.id = 123
b.a_id = 13

puts b.id
puts b.a_id

Test.dump_b(b)

or ffi.rb

require 'ffi'

module Test
  extend FFI::Library

  ffi_lib 'data.dylib'

  class A < FFI::Struct
    layout :id,  :int
  end

  class B < FFI::Struct
    layout :id,  :int,
           :a_nested, A
  end

  attach_function :dump_b, [:pointer], :void
end

a = Test::A.new

a[:id] = 3000

b = Test::B.new

b[:id] = 1000
b[:a_nested] = a

puts b[:id]
puts b[:a_nested][:id]

Test.dump_b(b)

Result

$ gcc -c data.c
$ gcc -dynamiclib data.o -o data.dylib
$ ruby fiddle.rb
123
13
B.b_id: 123
B.a_nested.a_id: 13
$ ruby ffi.rb
1000
3000
B.b_id: 1000
B.a_nested.a_id: 3000