Passing structs by value via ffi in ruby/jruby
I was stumped for a few hours on passing FFI::Structs into external routines, luckily, this post, 'Functions returning structures' (groups/google/ruby-ffi), tipped me off by showing how to return a struct by value:
From the C code:
...
typedef struct
{
int r, g, b, a;
} ALLEGRO_COLOR;
...
And the correct ruby FFI code:
...
class ALLEGRO_COLOR < FFI::Struct
layout :r, :float,
:g, :float,
:b, :float,
:a, :float
end
attach_function :al_map_rgb, [:uchar, :uchar, :uchar], ALLEGRO_COLOR.by_value
...
The existing FFI documentation is anemic in this area, and focuses on the more complex, though yet, more often used passing of pointer references to FFI::Structs, making it not obvious what to do with routines to make use of passing in structs 'by value'. Though, had I examined the methods offered by my derived GSL_Complex < FFI::Struct, I might have noticed the 'by_value'. Offering documentation help to Wayne Meissner
Now I have the means to wrapper up the GSL (Gnu-Scientific Library) routines for my gsl4r work. The GSL library routines covering complex numbers pass around structs by value in a big way.
My ruby ffi code:
... attach_function :gsl_complex_add, [ GSL_Complex.by_value, GSL_Complex.by_value ], GSL_Complex.by_value ...
Demo:
colby@gks lib $ jirb -r gsl4r irb(main):001:0> include GSL4r => Object irb(main):002:0> a=GSL_Complex.new => (0.0,0.0) irb(main):003:0> a.set(1,1) => (1.0,1.0) irb(main):004:0> b=GSL_Complex.new => (0.0,0.0) irb(main):005:0> b.set(2,2) => (2.0,2.0) irb(main):006:0> c=GSL4r::gsl_complex_add(a,b) => (3.0,3.0)
Now, my next question is, should it be possible to define an initializer for a class that inherits from FFI::Struct?
