Subject: [ruby-ffi] how to support arrays of structs |
From: Chuck Remes |
Date: 5/8/10 1:26 PM |
To: ruby-ffi@googlegroups.com |
I have a C function call that takes a pointer to an array of structs. I've searched the ML, examples and existing projects using FFI but I haven't found anything yet that covers that case. I want to ask if this is a reasonable methodology to mimic that behavior. Here's some code. module Lib # not showing everything... type struct foo_t { long a; long b; long c; char *d; }; int bar(foo_t *array, int len); Ideally I would like to work with that kind of C like it was ruby. attach_function :bar, [:pointer, :int], :int Foo < FFI::Struct layout :a, :long, :b, :long, :c, :long, :d, :pointer end end # module my_array = [] my_array << Foo.new my_array << Foo.new my_array << Foo.new Lib.bar my_array, my_array.size That doesn't work presumably because +my_array+ doesn't necessarily point to the beginning of the C or Java array backing the Ruby array. The C function then starts reading bogus data and potentially trampling over stuff it shouldn't. However, I think this might work. mem_chunk_ptr = FFI::MemoryPointer.new(:char, Foo.size * number_of_items) foo1 = Foo.new mem_chunk_ptr foo2 = Foo.new(mem_chunk_ptr + Foo.size) etc. Now I can pass +mem_chunk_ptr+ to my C function and everything should be ordered in memory. The big downfall of this technique is it uses a static chunk of memory. If you ever need to dynamically add more Foo structs to the array and you run out of space in your memory chunk, you need to allocate a bigger one, relocate/copy all existing structs and free up the original memory chunk. Obviously this could all be wrapped up and made a little nicer. Should the first technique work with ruby arrays and I just have a different problem? If I'm right that it doesn't work (and I've tried), would a patch implementing the behavior I described be accepted into FFI core? cr