Save 37% off PRO during our Black Friday Sale! »

Extending Ruby with C

Extending Ruby with C

A Learning Lunch presentation about writing C extensions for Ruby.

Beb7f5dd655d8b8e9093ef4fc5e59b6e?s=128

Paul Mucur

May 08, 2012
Tweet

Transcript

  1. EXTENDING RUBY with C

  2. Why?

  3. PERFORMANCE

  4. PERFORMANCE

  5. C BINDINGS

  6. C BINDINGS FFI

  7. None
  8. None
  9. array  <<  1

  10. static  VALUE rb_ary_push_1(VALUE  ary,  VALUE  item) {      

     long  idx  =  RARRAY_LEN(ary);        if  (idx  >=  ARY_CAPA(ary))  {                ary_double_capa(ary,  idx);        }        RARRAY_PTR(ary)[idx]  =  item;        ARY_SET_LEN(ary,  idx  +  1);        return  ary; }
  11. EXT/WORLD/WORLD.C

  12. >  World.hello =>  "Hello,  World!"

  13. require  "world" describe  World  do    describe  "#hello"  do  

         it  "greets  the  world"  do            World.hello.should  ==  "Hello,  World!"        end    end end
  14. module  World    module_function    def  hello      

     "Hello,  World!"    end end
  15. None
  16. HELLO

  17. return  rb_str_new("Hello,  World!",  13);

  18. static  VALUE  world_hello(VALUE  obj)  {    return  rb_str_new("Hello,  World!",  13);

    }
  19. WORLD

  20. VALUE  world_mWorld  =  rb_define_module("World"); rb_define_module_function(world_mWorld,  "hello",        world_hello,

     0);
  21. #include  <ruby.h> static  VALUE  world_hello(VALUE  obj)  {    return  rb_str_new("Hello,

     World!",  13); } void  Init_world(void)  {    VALUE  world_mWorld  =  rb_define_module("World");    rb_define_module_function(world_mWorld,  "hello",            world_hello,  0); }
  22. COMPILATION

  23. require  "mkmf"

  24. require  "mkmf" $CFLAGS  <<  "  -­‐Wall  -­‐Wextra" create_makefile("world")

  25. $  ruby  ext/world/extconf.rb creating  Makefile

  26. $  make compiling  ext/world/world.c linking  shared-­‐object  world.bundle

  27. $  rspec  spec/world_spec.rb   . Finished  in  0.00399  seconds 1

     example,  0  failures
  28. None
  29. $  rake  compile

  30. require  'rake/extensiontask' require  'rspec/core/rake_task' Rake::ExtensionTask.new('world') RSpec::Core::RakeTask.new('test') task  :test    

       =>  :compile task  :default  =>  :test
  31. it  "greets  someone  by  name,  if  given"  do    World.hello("Bob").should

     ==  "Hello,  Bob!" end
  32. “If argc is -1, the function will be called as:

    VALUE func(int argc, VALUE *argv, VALUE obj) where argc is the actual number of arguments, argv is the C array of the arguments, and obj is the receiver.”
  33. def  hello(name  =  nil)    if  name      

     "Hello,  #{name}!"    else        "Hello,  World!"    end end
  34. rb_define_module_function(world_mWorld,        "hello",  world_hello,  -­‐1);

  35. static  VALUE  world_hello(int  argc,  VALUE  *argv,  VALUE  obj)  {  

     VALUE  name;    rb_scan_args(argc,  argv,  "01",  &name);        ... }
  36. static  VALUE  world_hello(int  argc,  VALUE  *argv,  VALUE  obj)  {  

     VALUE  name;    rb_scan_args(argc,  argv,  "01",  &name);    if  (NIL_P(name))  {        return  rb_str_new("Hello,  World!",  13);    }  else  {        ...    } }
  37. static  VALUE  world_hello(int  argc,  VALUE  *argv,  VALUE  obj)  {  

     VALUE  name,  greeting;    rb_scan_args(argc,  argv,  "01",  &name);    if  (NIL_P(name))  {        greeting  =  rb_str_new("Hello,  World!",  13);    }  else  {        greeting  =  rb_str_new("Hello,  ",  7);        rb_str_cat(greeting,  RSTRING_PTR(name),  RSTRING_LEN(name));        rb_str_cat(greeting,  "!",  1);    }    return  greeting; }
  38. $  rake  clean  test rm  -­‐r  tmp/x86_64-­‐darwin11.3.0/world/1.9.3 mkdir  -­‐p  tmp/x86_64-­‐darwin11.3.0/world/1.9.3

    cd  tmp/x86_64-­‐darwin11.3.0/world/1.9.3 /Users/mudge/.rbenv/versions/1.9.3-­‐p125/bin/ruby  -­‐ I.  ../../../../ext/world/extconf.rb creating  Makefile cd  -­‐ cd  tmp/x86_64-­‐darwin11.3.0/world/1.9.3 make compiling  ../../../../ext/world/world.c linking  shared-­‐object  world.bundle cd  -­‐ install  -­‐c  tmp/x86_64-­‐darwin11.3.0/world/1.9.3/world.bundle  lib/ world.bundle /Users/mudge/.rbenv/versions/1.9.3-­‐p125/bin/ruby  -­‐S  rspec  ./ spec/world_spec.rb .. Finished  in  0.00081  seconds 2  examples,  0  failures
  39. None
  40. QUESTIONS?