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