SlideShare una empresa de Scribd logo
1 de 42
Happy
Independence
         Day
Ruby
C Extensions


               Matt Todd
GeoIP
#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");
db = GeoIP::Organization.new("GeoIPOrg.dat", :memory)
name = db.look_up('24.24.24.24')
Basics
// 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
}
// include the Ruby objects, data types, macros, and mechanisms
#include "ruby.h"




         defines classes,
        keywords, values,
        functions, macros
// define Ruby value variable
VALUE HelloWorld = Qnil;




     creates variable to
    hold class definition
// prototype the init function that defines the extension class
void Init_hello_world();




        prototype for init
            function
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
API
ReceiverClass =
rb_define_class(
  "RubyClassName",
  rb_cParentClass);

ReceiverModule =
rb_define_module(
  "RubyModuleName")
SubReceiverClass =
rb_define_class_under(
  ReceiverClass
  "SubRubyClassName",
  rb_cParentClass);
rb_define_method(
  ReceiverClass,
  "ruby_method_name",
  implementation_function,
  number_of_arguments);
implementation_function


Returns a Ruby value         the receiver
VALUE implementation_function(VALUE self) {
  return Qnil; return nil
}
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);
rb_scan_args(
  int argc, VALUE *args,
  char *format,
  vars...);
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)
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;
}
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);
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);
evaluation
VALUE rb_eval_string(
  char *string);

VALUE rb_funcall(
  VALUE receiver,
  ID rb_intern("meth"),
  int argc, VALUE *args);
Examples
// 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();
                                                                 }
class Foo
  class Base
    def foo!
      # deep, dark magic here
      true
    end
  end
end
class Bar < Foo::Base; end

@bar = Bar.new
@bar.foo! #=> true
#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
}
#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
}
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
}
#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
}
#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
}
module ActsAsFoo
  def foo?
    true
  end

  def included(target)
    target.extend ClassMethods
  end
  module ClassMethods
    def foo?
      true
    end
  end
end
class Bar < Foo
  include ActsAsFoo
end

Bar.foo? #=> true
@bar = Bar.new
@bar.foo? #=> true
#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);
}
#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);
}
rb_include_module(Bar, ActsAsFoo);
// call ActsAsFoo.included(Bar) manually since rb_include_module doesn't
rb_funcall(ActsAsFoo, rb_intern("included"), 1, Bar);
Fin.
http://github.com/mtodd/ruby-c
Resources
http://rubycentral.com/pickaxe/ext_ruby.html

Más contenido relacionado

La actualidad más candente

Mod Perl Quick Reference Card
Mod Perl Quick Reference CardMod Perl Quick Reference Card
Mod Perl Quick Reference Card
Faryne Hsieh
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
Juriy Zaytsev
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisa
ujihisa
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
Inheritance patterns
Inheritance patternsInheritance patterns
Inheritance patterns
Luke Smith
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programming
jeffz
 
Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011
Rafael Soto
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
jeffz
 
Coffee script
Coffee scriptCoffee script
Coffee script
timourian
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 

La actualidad más candente (20)

Mod Perl Quick Reference Card
Mod Perl Quick Reference CardMod Perl Quick Reference Card
Mod Perl Quick Reference Card
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
 
PHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP LimogesPHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP Limoges
 
ekb.py - Python VS ...
ekb.py - Python VS ...ekb.py - Python VS ...
ekb.py - Python VS ...
 
Lazy Data Using Perl
Lazy Data Using PerlLazy Data Using Perl
Lazy Data Using Perl
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisa
 
Basic Mechanism of OOPL
Basic Mechanism of OOPLBasic Mechanism of OOPL
Basic Mechanism of OOPL
 
Objective-C A Beginner's Dive
Objective-C A Beginner's DiveObjective-C A Beginner's Dive
Objective-C A Beginner's Dive
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oop
 
Extending Python - EuroPython 2014
Extending Python - EuroPython 2014Extending Python - EuroPython 2014
Extending Python - EuroPython 2014
 
Inheritance patterns
Inheritance patternsInheritance patterns
Inheritance patterns
 
Txjs
TxjsTxjs
Txjs
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programming
 
The promise of asynchronous PHP
The promise of asynchronous PHPThe promise of asynchronous PHP
The promise of asynchronous PHP
 
Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
 
Coffee script
Coffee scriptCoffee script
Coffee script
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Core concepts-javascript
Core concepts-javascriptCore concepts-javascript
Core concepts-javascript
 

Destacado

Sgp Power Point 1st Submission
Sgp Power Point 1st SubmissionSgp Power Point 1st Submission
Sgp Power Point 1st Submission
AliciaAnn1
 
Guerra de las Galias Texto 5 1ª Evaluación
Guerra de las Galias Texto 5 1ª EvaluaciónGuerra de las Galias Texto 5 1ª Evaluación
Guerra de las Galias Texto 5 1ª Evaluación
Fátima Prieto
 

Destacado (7)

计算思维在儿童数字文化创作课程中的地位与培养
计算思维在儿童数字文化创作课程中的地位与培养计算思维在儿童数字文化创作课程中的地位与培养
计算思维在儿童数字文化创作课程中的地位与培养
 
Intro to Merb
Intro to MerbIntro to Merb
Intro to Merb
 
Building A Framework On Rack
Building A Framework On RackBuilding A Framework On Rack
Building A Framework On Rack
 
儿童数字文化创作课程与信息技术课程的变革
儿童数字文化创作课程与信息技术课程的变革儿童数字文化创作课程与信息技术课程的变革
儿童数字文化创作课程与信息技术课程的变革
 
Learning classifiers from discretized expression quantitative trait loci
Learning classifiers from discretized expression quantitative trait lociLearning classifiers from discretized expression quantitative trait loci
Learning classifiers from discretized expression quantitative trait loci
 
Sgp Power Point 1st Submission
Sgp Power Point 1st SubmissionSgp Power Point 1st Submission
Sgp Power Point 1st Submission
 
Guerra de las Galias Texto 5 1ª Evaluación
Guerra de las Galias Texto 5 1ª EvaluaciónGuerra de las Galias Texto 5 1ª Evaluación
Guerra de las Galias Texto 5 1ª Evaluación
 

Similar a Writing Ruby Extensions

Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
Miao Siyu
 
Orlando BarCamp Why Javascript Doesn't Suck
Orlando BarCamp Why Javascript Doesn't SuckOrlando BarCamp Why Javascript Doesn't Suck
Orlando BarCamp Why Javascript Doesn't Suck
erockendude
 
Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2
drewz lin
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 
Understanding PHP objects
Understanding PHP objectsUnderstanding PHP objects
Understanding PHP objects
julien pauli
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 
all i need is these two filesCreate VectorContainer.hppCreat.docx
all i need is these two filesCreate VectorContainer.hppCreat.docxall i need is these two filesCreate VectorContainer.hppCreat.docx
all i need is these two filesCreate VectorContainer.hppCreat.docx
jack60216
 

Similar a Writing Ruby Extensions (20)

JavaScript Primer
JavaScript PrimerJavaScript Primer
JavaScript Primer
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
 
Orlando BarCamp Why Javascript Doesn't Suck
Orlando BarCamp Why Javascript Doesn't SuckOrlando BarCamp Why Javascript Doesn't Suck
Orlando BarCamp Why Javascript Doesn't Suck
 
Javascript
JavascriptJavascript
Javascript
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2
 
Introduction to php oop
Introduction to php oopIntroduction to php oop
Introduction to php oop
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
Prototype
PrototypePrototype
Prototype
 
Understanding PHP objects
Understanding PHP objectsUnderstanding PHP objects
Understanding PHP objects
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Virtual Functions
Virtual FunctionsVirtual Functions
Virtual Functions
 
6976.ppt
6976.ppt6976.ppt
6976.ppt
 
Class 3 - PHP Functions
Class 3 - PHP FunctionsClass 3 - PHP Functions
Class 3 - PHP Functions
 
all i need is these two filesCreate VectorContainer.hppCreat.docx
all i need is these two filesCreate VectorContainer.hppCreat.docxall i need is these two filesCreate VectorContainer.hppCreat.docx
all i need is these two filesCreate VectorContainer.hppCreat.docx
 
Message in a bottle
Message in a bottleMessage in a bottle
Message in a bottle
 

Último

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Último (20)

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 

Writing Ruby Extensions

  • 1.
  • 3.
  • 4. Ruby C Extensions Matt Todd
  • 6. #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");
  • 7. db = GeoIP::Organization.new("GeoIPOrg.dat", :memory) name = db.look_up('24.24.24.24')
  • 9. // 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 }
  • 10. // include the Ruby objects, data types, macros, and mechanisms #include "ruby.h" defines classes, keywords, values, functions, macros
  • 11. // define Ruby value variable VALUE HelloWorld = Qnil; creates variable to hold class definition
  • 12. // prototype the init function that defines the extension class void Init_hello_world(); prototype for init function
  • 13. 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
  • 14. API
  • 15. ReceiverClass = rb_define_class( "RubyClassName", rb_cParentClass); ReceiverModule = rb_define_module( "RubyModuleName")
  • 16. SubReceiverClass = rb_define_class_under( ReceiverClass "SubRubyClassName", rb_cParentClass);
  • 17. rb_define_method( ReceiverClass, "ruby_method_name", implementation_function, number_of_arguments);
  • 18. implementation_function Returns a Ruby value the receiver VALUE implementation_function(VALUE self) { return Qnil; return nil }
  • 19. 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);
  • 20. rb_scan_args( int argc, VALUE *args, char *format, vars...);
  • 21. 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)
  • 22. 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; }
  • 23. 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);
  • 24. 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);
  • 25. evaluation VALUE rb_eval_string( char *string); VALUE rb_funcall( VALUE receiver, ID rb_intern("meth"), int argc, VALUE *args);
  • 27. // 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(); }
  • 28. class Foo class Base def foo! # deep, dark magic here true end end end
  • 29. class Bar < Foo::Base; end @bar = Bar.new @bar.foo! #=> true
  • 30. #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 }
  • 31. #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 }
  • 32. 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 }
  • 33. #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 }
  • 34. #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 }
  • 35. module ActsAsFoo def foo? true end def included(target) target.extend ClassMethods end module ClassMethods def foo? true end end end
  • 36. class Bar < Foo include ActsAsFoo end Bar.foo? #=> true @bar = Bar.new @bar.foo? #=> true
  • 37. #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); }
  • 38. #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); }
  • 39. rb_include_module(Bar, ActsAsFoo); // call ActsAsFoo.included(Bar) manually since rb_include_module doesn't rb_funcall(ActsAsFoo, rb_intern("included"), 1, Bar);
  • 40. Fin.