ffi -- creating cross engine rubygems

Post on 15-May-2015

1.637 Views

Category:

Technology

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

FFI is a way to create cross engine rubygems. Wrap a library once, and use it from MRI, JRuby, Rubinious, and mingw32 Ruby. This talk will discuss FFI why you want to use it.

TRANSCRIPT

FFIMAKING CROSS ENGINE EXTENSIONS

Jeremy Hinegardnerjeremy@copiousfreetime.org

twitter : copiousfreetime

1Tuesday, November 24, 2009

I LOVE RUBY

2Tuesday, November 24, 2009

I LIKE C

3Tuesday, November 24, 2009

SURVEY TIME

4Tuesday, November 24, 2009

RUBY DEVELOPERS?

5Tuesday, November 24, 2009

WRITER OF LIBRARIES?

6Tuesday, November 24, 2009

WRITER OF EXTENSIONS?

7Tuesday, November 24, 2009

USED BY MULTIPLE ENGINES?

8Tuesday, November 24, 2009

WHAT IS FFI?

9Tuesday, November 24, 2009

LIBFFIhttp://sourceware.org/libffi/

“A foreign function interface is the popular name for the interface that allows code written in one language

to call code written in another language.”

10Tuesday, November 24, 2009

FOR RUBYISTS

The Goal :

An extension based upon FFI should be compatible with many ruby

engines.

11Tuesday, November 24, 2009

libfoo.so

12Tuesday, November 24, 2009

libfoo.so

Applicationuses

libfoo_bar()

12Tuesday, November 24, 2009

libfoo.so

Applicationuses

libfoo_bar()

FFI

12Tuesday, November 24, 2009

libfoo.so

Applicationuses

libfoo_bar()

FFIRuntim

e

12Tuesday, November 24, 2009

libfoo.so

ruby-foo C extension

Matz RubyInterpreter

App

13Tuesday, November 24, 2009

libfoo.so

ruby-foo C extension

Matz RubyInterpreter

App

JRubyInterpreter

App

RubiniusInterpreter

App

13Tuesday, November 24, 2009

libfoo.so

Matz RubyInterpreter

App

JRubyInterpreter

App

RubiniusInterpreter

App

13Tuesday, November 24, 2009

libfoo.so

Matz RubyInterpreter

App

JRubyInterpreter

App

RubiniusInterpreter

App

13Tuesday, November 24, 2009

libfoo.so

Matz RubyInterpreter

App

JRubyInterpreter

App

RubiniusInterpreter

App

built-in libffi or ffi gem

13Tuesday, November 24, 2009

libfoo.so

Matz RubyInterpreter

App

JRubyInterpreter

App

RubiniusInterpreter

App

built-in libffi or ffi gem

foo-ffi (pure ruby)

13Tuesday, November 24, 2009

LIBSIMPLE_METRICShttp://github.com/copiousfreetime/libsimple_metrics

14Tuesday, November 24, 2009

 1 #ifndef __SIMPLE_METRICS_H__ 2 #define __SIMPLE_METRICS_H__ 3 #include <stdlib.h> 4 #include <math.h> 5  6 typedef struct _simple_metrics{ 7     double min; 8     double max; 9     double sum;10     double sumsq;11     long   count;12 } simple_metrics ;13 14 simple_metrics* simple_metrics_new();15 void            simple_metrics_free(   simple_metrics* sm );16 void            simple_metrics_update( simple_metrics* sm, double value );17 double          simple_metrics_mean(   simple_metrics* sm );18 double          simple_metrics_min(    simple_metrics* sm );19 double          simple_metrics_max(    simple_metrics* sm );20 double          simple_metrics_sum(    simple_metrics* sm );21 long            simple_metrics_count(  simple_metrics* sm );22 double          simple_metrics_stddev( simple_metrics* sm );23 double          simple_metrics_rate(   simple_metrics* sm );24 25 #endif

15Tuesday, November 24, 2009

 1 class Metric 2   attr_reader :name 3   def initialize( name ) 4     @name 5   end 6  7   def update( new_value) ... end 8   def count  ... end 9   def max    ... end10   def mean   ... end11   def min    ... end12   def rate   ... end13   def sum    ... end14   def stddev ... end15 end

16Tuesday, November 24, 2009

142 void Init_simple_metrics_ext()143 {144     VALUE cSM_Common;145 146     mSM  = rb_define_module( "SimpleMetrics" );147     mSME = rb_define_module_under( mSM, "Ext" );148 149     /* load the class we inherit from */150     rb_require("simplemetrics/common");151 152     cSM_Common = rb_const_get( mSM, rb_intern( "Common" ) );153 154     cSME_Metric = rb_define_class_under( mSME, "Metric", cSM_Common );155 156     rb_define_alloc_func(cSME_Metric, sm_alloc); 157     rb_define_method( cSME_Metric, "initialize", sm_initialize, 1 );158     rb_define_method( cSME_Metric, "update", sm_update, 1 );159     rb_define_method( cSME_Metric, "count", sm_count, 0 );160     rb_define_method( cSME_Metric, "max", sm_max, 0 );161     rb_define_method( cSME_Metric, "min", sm_min, 0 );162     rb_define_method( cSME_Metric, "mean", sm_mean, 0 );163     rb_define_method( cSME_Metric, "rate", sm_rate, 0 );164     rb_define_method( cSME_Metric, "sum", sm_sum, 0 );165     rb_define_method( cSME_Metric, "stddev", sm_stddev, 0 );166 167 }

17Tuesday, November 24, 2009

142 void Init_simple_metrics_ext()143 {144     VALUE cSM_Common;145 146     mSM  = rb_define_module( "SimpleMetrics" );147     mSME = rb_define_module_under( mSM, "Ext" );148 149     /* load the class we inherit from */150     rb_require("simplemetrics/common");151 152     cSM_Common = rb_const_get( mSM, rb_intern( "Common" ) );153 154     cSME_Metric = rb_define_class_under( mSME, "Metric", cSM_Common );155 156     rb_define_alloc_func(cSME_Metric, sm_alloc); 157     rb_define_method( cSME_Metric, "initialize", sm_initialize, 1 );158     rb_define_method( cSME_Metric, "update", sm_update, 1 );159     rb_define_method( cSME_Metric, "count", sm_count, 0 );160     rb_define_method( cSME_Metric, "max", sm_max, 0 );161     rb_define_method( cSME_Metric, "min", sm_min, 0 );162     rb_define_method( cSME_Metric, "mean", sm_mean, 0 );163     rb_define_method( cSME_Metric, "rate", sm_rate, 0 );164     rb_define_method( cSME_Metric, "sum", sm_sum, 0 );165     rb_define_method( cSME_Metric, "stddev", sm_stddev, 0 );166 167 }

17Tuesday, November 24, 2009

7 module SimpleMetrics 8   module FFI 9 10     class Struct < ::FFI::ManagedStruct11       layout :min, :double, :max, :double, :sum, :double, 12              :sumsq, :double, :count, :long13       def self.release( ptr )14         SimpleMetrics::FFI.simple_metrics_free( ptr )15       end16     end17 18     extend ::FFI::Library19     ffi_lib "libsimple_metrics"20 21     attach_function :simple_metrics_new,   [          ], :pointer22     attach_function :simple_metrics_free,  [ :pointer ], :void23     attach_function :simple_metrics_update,[ :pointer, :double  ], :void24     attach_function :simple_metrics_min,   [ :pointer ], :double25     attach_function :simple_metrics_max,   [ :pointer ], :double26     attach_function :simple_metrics_mean,  [ :pointer ], :double27     attach_function :simple_metrics_sum,   [ :pointer ], :double28     attach_function :simple_metrics_count, [ :pointer ], :long29     attach_function :simple_metrics_stddev,[ :pointer ], :double30     attach_function :simple_metrics_rate,  [ :pointer ], :double31 32   end33 end

18Tuesday, November 24, 2009

7 module SimpleMetrics 8   module FFI 9 10     class Struct < ::FFI::ManagedStruct11       layout :min, :double, :max, :double, :sum, :double, 12              :sumsq, :double, :count, :long13       def self.release( ptr )14         SimpleMetrics::FFI.simple_metrics_free( ptr )15       end16     end17 18     extend ::FFI::Library19     ffi_lib "libsimple_metrics"20 21     attach_function :simple_metrics_new,   [          ], :pointer22     attach_function :simple_metrics_free,  [ :pointer ], :void23     attach_function :simple_metrics_update,[ :pointer, :double  ], :void24     attach_function :simple_metrics_min,   [ :pointer ], :double25     attach_function :simple_metrics_max,   [ :pointer ], :double26     attach_function :simple_metrics_mean,  [ :pointer ], :double27     attach_function :simple_metrics_sum,   [ :pointer ], :double28     attach_function :simple_metrics_count, [ :pointer ], :long29     attach_function :simple_metrics_stddev,[ :pointer ], :double30     attach_function :simple_metrics_rate,  [ :pointer ], :double31 32   end33 end

library function parameters return type

18Tuesday, November 24, 2009

35 module SimpleMetrics36   module FFI37     class Metric < ::SimpleMetrics::Common38       include ::SimpleMetrics::FFI39       def initialize( name )40         super41         @impl = FFI.simple_metrics_new42       end43 44       def update( v )45         simple_metrics_update( @impl, v )46       end47 48       self.keys.each do |f|49         module_eval <<-code50         def #{f}51           simple_metrics_#{f}( @impl )52         end53         code54       end55     end56   end57 end

19Tuesday, November 24, 2009

10 class Struct < ::FFI::ManagedStruct11   layout :min, :double, 12          :max, :double, 13          :sum, :double, 14          :sumsq, :double, 15          :count, :long16   def self.release( ptr )17     SimpleMetrics::FFI.simple_metrics_free( ptr )18   end19 end

 6 typedef struct _simple_metrics{ 7     double min; 8     double max; 9     double sum;10     double sumsq;11     long   count;12 } simple_metrics ;

20Tuesday, November 24, 2009

14 simple_metrics* simple_metrics_new();15 void            simple_metrics_free(   simple_metrics* sm );16 void            simple_metrics_update( simple_metrics* sm, double value );17 double          simple_metrics_mean(   simple_metrics* sm );18 double          simple_metrics_min(    simple_metrics* sm );19 double          simple_metrics_max(    simple_metrics* sm );20 double          simple_metrics_sum(    simple_metrics* sm );21 long            simple_metrics_count(  simple_metrics* sm );22 double          simple_metrics_stddev( simple_metrics* sm );23 double          simple_metrics_rate(   simple_metrics* sm );

21 extend ::FFI::Library22 ffi_lib "libsimple_metrics"23 24 attach_function :simple_metrics_new,   [          ], :pointer25 attach_function :simple_metrics_free,  [ :pointer ], :void26 attach_function :simple_metrics_update,[ :pointer, :double  ], :void27 attach_function :simple_metrics_mean,  [ :pointer ], :double28 attach_function :simple_metrics_min,   [ :pointer ], :double29 attach_function :simple_metrics_max,   [ :pointer ], :double30 attach_function :simple_metrics_sum,   [ :pointer ], :double31 attach_function :simple_metrics_count, [ :pointer ], :long32 attach_function :simple_metrics_stddev,[ :pointer ], :double33 attach_function :simple_metrics_rate,  [ :pointer ], :double

21Tuesday, November 24, 2009

FFI Traditional C Extension

Jeremy’s Time

1 Million update() calls

Will it Blend run on JRuby?

40 minutes 70 minutes

1.16 sec 0.42 sec

Yes No

MEANINGLESS METRICS

22Tuesday, November 24, 2009

DEMO

23Tuesday, November 24, 2009

% ruby example/bench.rb 1000000generating 1000000 random numbers between 0 and 10,000Rehearsal -----------------------------------------------ext 0.500000 0.000000 0.500000 ( 0.504501)ffi 0.960000 0.000000 0.960000 ( 0.956847)-------------------------------------- total: 1.460000sec

user system total realext 0.510000 0.000000 0.510000 ( 0.521388)ffi 0.940000 0.000000 0.940000 ( 0.946538)

% ~/pkgs/jruby-1.4.0/bin/jruby example/bench.rb 1000000generating 1000000 random numbers between 0 and 10,000Rehearsal -----------------------------------------------ffi 0.697000 0.000000 0.697000 ( 0.696000)-------------------------------------- total: 0.697000sec

user system total realffi 0.493000 0.000000 0.493000 ( 0.493000)

24Tuesday, November 24, 2009

FFI BASED PROJECTS

Nokogiri ffi-wiiuse

Gnu Linear Programming Toolkit NiceFFI

Ruby-SDL-FFI

Rubygameffi-inliner

ffi-opengl

ffi-life

ffi-tccJohnson FFI port

rufus-tokyo

ffi-tk

Ruby-GIR-FFI

ffi-opencl

25Tuesday, November 24, 2009

THANKS

•Wayne Meissner - adding libffi to JRuby and providing the ffi gem for MRI.

• Evan Phoenix - using libffi in Rubinius

• Authors of the examples on the ffi project wiki

26Tuesday, November 24, 2009

LINKS

• http://github.com/ffi/ffi

• http://wmeissner.blogspot.com/

• http://groups.google.com/group/ruby-ffi

27Tuesday, November 24, 2009

QUESTIONS?

28Tuesday, November 24, 2009

top related