Nested structures in Ruby Fiddle

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

Leave a Comment

tech