38
  • 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).

Rann Lifshitz
  • 4,040
  • 4
  • 22
  • 42
Ríša Werner
  • 501
  • 3
  • 6
  • Maybe using the `Fiddle::CParser` (http://www.rubydoc.info/stdlib/dl/2.0.0/DL/CParser) you can get access to the nested structs. – Zach Tuttle Jul 12 '17 at 20:10
  • Well, `Fiddle::CParser` is the problem, because for structure signatures it uses `parse_ctype` for each member of the struct and it doesn't recognize anything but basic types. – Ríša Werner Jul 19 '17 at 09:33
  • Have you looked at `Fiddle::CStructBuilder`? http://ruby-doc.org/stdlib-2.0.0/libdoc/fiddle/rdoc/Fiddle/CStructBuilder.html – Prajjwal Aug 12 '17 at 11:06

1 Answers1

1

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
bliof
  • 2,957
  • 2
  • 23
  • 39