SlideShare a Scribd company logo
1 of 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

More Related Content

What's hot

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
 

What's hot (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
 

Viewers also liked

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
 

Viewers also liked (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 to 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 to 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
 

Recently uploaded

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

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
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
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
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
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
 
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
 
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, ...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
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...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
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...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 

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.