Writing Ruby Extensions

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Favorites, Groups & Events

    Writing Ruby Extensions - Presentation Transcript

    1. Happy Independence Day
    2. Ruby C Extensions Matt Todd
    3. GeoIP
    4. #include <GeoIP.h> GeoIP *gi; char *name = NULL; gi = GeoIP_open("GeoIPOrg.dat", GEOIP_MEMORY_CACHE); name = GeoIP_name_by_addr(gi, "24.24.24.24");
    5. db = GeoIP::Organization.new("GeoIPOrg.dat", :memory) name = db.look_up('24.24.24.24')
    6. Basics
    7. // include the Ruby objects, data types, macros, and mechanisms #include "ruby.h" // define Ruby value variable VALUE HelloWorld = Qnil; // prototype the init function that defines the extension class void Init_hello_world(); // extension initialization function void Init_hello_world() { // class constant Ruby constant name parent class HelloWorld = rb_define_class("HelloWorld", rb_cObject); // Init other classes/modules }
    8. // include the Ruby objects, data types, macros, and mechanisms #include "ruby.h" defines classes, keywords, values, functions, macros
    9. // define Ruby value variable VALUE HelloWorld = Qnil; creates variable to hold class definition
    10. // prototype the init function that defines the extension class void Init_hello_world(); prototype for init function
    11. init function defines Ruby class interface and any methods // extension initialization function void Init_hello_world() { // class constant Ruby constant name parent class HelloWorld = rb_define_class("HelloWorld", rb_cObject); // Init other classes/modules } calls other init funcs
    12. API
    13. ReceiverClass = rb_define_class( "RubyClassName", rb_cParentClass); ReceiverModule = rb_define_module( "RubyModuleName")
    14. SubReceiverClass = rb_define_class_under( ReceiverClass "SubRubyClassName", rb_cParentClass);
    15. rb_define_method( ReceiverClass, "ruby_method_name", implementation_function, number_of_arguments);
    16. implementation_function Returns a Ruby value the receiver VALUE implementation_function(VALUE self) { return Qnil; return nil }
    17. number_of_arguments 0..17 => VALUE func(VALUE self, VALUE param1, ...); -1 => VALUE func(int argc, VALUE *args, VALUE self); -2 => VALUE func(VALUE self, VALUE *args);
    18. rb_scan_args( int argc, VALUE *args, char *format, vars...);
    19. format /(d)?(d)?(*)?(&)?/ number_of_mandatory_args number_of_optional_args splat? block? "1" => def meth(a) "01" => def meth(a = {}) "&" => def meth(&block) "11&" => def meth(a, b = {}, &block) "1*" => def meth(a, *rest)
    20. usage rb_define_method(Foo, "bar", rb_foo_bar, -1); VALUE rb_foo_bar(int argc, VALUE *args, VALUE self) { VALUE a, b; rb_scan_args(argc, args, "11", &a, &b); // default to 10 if b not supplied if(NIL_P(b)) { b = 10; } return a * b; }
    21. macros NIL_P(VALUE v); // #nil? // C => Ruby VALUE INT2NUM(int i); VALUE rb_str_new2(char *str); VALUE rb_float_new(double d); // Ruby => C int NUM2INT(VALUE i); double NUM2DBL(VALUE i); char* STR2CSTR(VALUE str);
    22. Ruby types VALUE str = rb_str_new2("yo"); VALUE ary = rb_ary_new(); rb_ary_push(ary, VALUE a); VALUE b = rb_ary_pop(ary); VALUE hash = rb_hash_new(); rb_hash_aset(hash, VALUE key, VALUE a); rb_hash_aref(hash, VALUE key);
    23. evaluation VALUE rb_eval_string( char *string); VALUE rb_funcall( VALUE receiver, ID rb_intern("meth"), int argc, VALUE *args);
    24. Examples
    25. // ActsAsFoo #include "ruby.h" VALUE rb_ActsAsFoo_foo_q(VALUE self) { return Qtrue; VALUE ClassesAndModulesSample = Qnil; } VALUE Foo = Qnil; VALUE rb_ActsAsFoo_included(VALUE self, VALUE target) { VALUE Foo_Base = Qnil; rb_extend_object(target, ActsAsFoo_ClassMethods); VALUE Bar = Qnil; return self; } VALUE ActsAsFoo = Qnil; VALUE ActsAsFoo_ClassMethods = Qnil; void Init_acts_as_foo() { ActsAsFoo = rb_define_module("ActsAsFoo"); void Init_classes_and_modules_sample(); rb_define_method(ActsAsFoo, "foo?", rb_ActsAsFoo_foo_q, 0); rb_define_singleton_method(ActsAsFoo, "included", rb_ActsAsFoo_included, 1); // Foo ActsAsFoo_ClassMethods = rb_define_module_under(ActsAsFoo, "ClassMethods"); VALUE rb_Foo_Base_find_b(VALUE self) { rb_define_method(ActsAsFoo_ClassMethods, "foo?", rb_ActsAsFoo_foo_q, 0); return Qtrue; } rb_include_module(Bar, ActsAsFoo); // call ActsAsFoo.included(Bar) manually since rb_include_module doesn't void Init_foo() { rb_funcall(ActsAsFoo, rb_intern("included"), 1, Bar); Foo = rb_define_class("Foo", rb_cObject); } Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject); /////////////////////////////////////////////////////////////////////////////// rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0); } void Init_classes_and_modules_sample() { ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", // Bar rb_cObject); void Init_bar() { Init_foo(); Bar = rb_define_class("Bar", Foo_Base); Init_bar(); // class Bar < Foo::Base; end } Init_acts_as_foo(); }
    26. class Foo class Base def foo! # deep, dark magic here true end end end
    27. class Bar < Foo::Base; end @bar = Bar.new @bar.foo! #=> true
    28. #include "ruby.h" VALUE ClassesAndModulesSample = Qnil; VALUE Foo = Qnil; VALUE Foo_Base = Qnil; VALUE Bar = Qnil; void Init_classes_and_modules_sample(); VALUE rb_Foo_Base_find_b(VALUE self) { return Qtrue; } void Init_foo() { Foo = rb_define_class("Foo", rb_cObject); Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject); rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0); } void Init_bar() { Bar = rb_define_class("Bar", Foo_Base); } void Init_classes_and_modules_sample() { ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", rb_cObject); Init_foo(); Init_bar(); // class Bar < Foo::Base; end }
    29. #include "ruby.h" VALUE ClassesAndModulesSample = Qnil; class Foo < Object VALUE Foo = Qnil; VALUE Foo_Base = Qnil; VALUE Bar = Qnil; void Init_classes_and_modules_sample(); VALUE rb_Foo_Base_find_b(VALUE self) { return Qtrue; } void Init_foo() { Foo = rb_define_class("Foo", rb_cObject); Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject); rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0); } void Init_bar() { Bar = rb_define_class("Bar", Foo_Base); } void Init_classes_and_modules_sample() { ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", rb_cObject); Init_foo(); Init_bar(); // class Bar < Foo::Base; end }
    30. class Foo < Object #include "ruby.h" VALUE ClassesAndModulesSample = Qnil; VALUE Foo = Qnil; class Base VALUE Foo_Base = Qnil; VALUE Bar = Qnil; void Init_classes_and_modules_sample(); VALUE rb_Foo_Base_find_b(VALUE self) { return Qtrue; } void Init_foo() { Foo = rb_define_class("Foo", rb_cObject); Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject); rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0); } void Init_bar() { Bar = rb_define_class("Bar", Foo_Base); } void Init_classes_and_modules_sample() { ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", rb_cObject); Init_foo(); Init_bar(); // class Bar < Foo::Base; end }
    31. #include "ruby.h" class Foo < Object VALUE ClassesAndModulesSample = Qnil; class Base VALUE Foo = Qnil; VALUE Foo_Base = Qnil; VALUE Bar = Qnil; def foo! void Init_classes_and_modules_sample(); VALUE rb_Foo_Base_find_b(VALUE self) { return Qtrue; } void Init_foo() { Foo = rb_define_class("Foo", rb_cObject); Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject); rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0); } void Init_bar() { Bar = rb_define_class("Bar", Foo_Base); } void Init_classes_and_modules_sample() { ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", rb_cObject); Init_foo(); Init_bar(); // class Bar < Foo::Base; end }
    32. #include "ruby.h" VALUE ClassesAndModulesSample = Qnil; VALUE Foo = Qnil; VALUE Foo_Base = Qnil; VALUE Bar = Qnil; void Init_classes_and_modules_sample(); VALUE rb_Foo_Base_find_b(VALUE self) { return Qtrue; } void Init_foo() { Foo = rb_define_class("Foo", rb_cObject); Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject); rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0); } void Init_bar() { Bar = rb_define_class("Bar", Foo_Base); } void Init_classes_and_modules_sample() { ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", rb_cObject); Init_foo(); Init_bar(); // class Bar < Foo::Base; end }
    33. module ActsAsFoo def foo? true end def included(target) target.extend ClassMethods end module ClassMethods def foo? true end end end
    34. class Bar < Foo include ActsAsFoo end Bar.foo? #=> true @bar = Bar.new @bar.foo? #=> true
    35. #include "ruby.h" VALUE ActsAsFoo = Qnil; VALUE ActsAsFoo_ClassMethods = Qnil; VALUE rb_ActsAsFoo_foo_q(VALUE self) { return Qtrue; } VALUE rb_ActsAsFoo_included(VALUE self, VALUE target) { rb_extend_object(target, ActsAsFoo_ClassMethods); return self; } void Init_acts_as_foo() { ActsAsFoo = rb_define_module("ActsAsFoo"); rb_define_method(ActsAsFoo, "foo?", rb_ActsAsFoo_foo_q, 0); rb_define_singleton_method(ActsAsFoo, "included", rb_ActsAsFoo_included, 1); ActsAsFoo_ClassMethods = rb_define_module_under(ActsAsFoo, "ClassMethods"); rb_define_method(ActsAsFoo_ClassMethods, "foo?", rb_ActsAsFoo_foo_q, 0); }
    36. #include "ruby.h" VALUE ActsAsFoo = Qnil; VALUE ActsAsFoo_ClassMethods = Qnil; VALUE rb_ActsAsFoo_foo_q(VALUE self) { return Qtrue; } VALUE rb_ActsAsFoo_included(VALUE self, VALUE target) { rb_extend_object(target, ActsAsFoo_ClassMethods); return self; } void Init_acts_as_foo() { ActsAsFoo = rb_define_module("ActsAsFoo"); rb_define_method(ActsAsFoo, "foo?", rb_ActsAsFoo_foo_q, 0); rb_define_singleton_method(ActsAsFoo, "included", rb_ActsAsFoo_included, 1); ActsAsFoo_ClassMethods = rb_define_module_under(ActsAsFoo, "ClassMethods"); rb_define_method(ActsAsFoo_ClassMethods, "foo?", rb_ActsAsFoo_foo_q, 0); }
    37. rb_include_module(Bar, ActsAsFoo); // call ActsAsFoo.included(Bar) manually since rb_include_module doesn't rb_funcall(ActsAsFoo, rb_intern("included"), 1, Bar);
    38. Fin.
    39. http://github.com/mtodd/ruby-c
    40. Resources http://rubycentral.com/pickaxe/ext_ruby.html
    SlideShare Zeitgeist 2009

    + Matt ToddMatt Todd Nominate

    custom

    1071 views, 0 favs, 0 embeds more stats

    A cursory overview of how to write Ruby extensions more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 1071
      • 1071 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 0
    • Downloads 6
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories