SlideShare une entreprise Scribd logo
1  sur  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

Contenu connexe

Tendances

Mod Perl Quick Reference Card
Mod Perl Quick Reference CardMod Perl Quick Reference Card
Mod Perl Quick Reference CardFaryne Hsieh
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Juriy Zaytsev
 
PHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP LimogesPHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP Limoges✅ William Pinaud
 
ekb.py - Python VS ...
ekb.py - Python VS ...ekb.py - Python VS ...
ekb.py - Python VS ...it-people
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisaujihisa
 
Basic Mechanism of OOPL
Basic Mechanism of OOPLBasic Mechanism of OOPL
Basic Mechanism of OOPLkwatch
 
Objective-C A Beginner's Dive
Objective-C A Beginner's DiveObjective-C A Beginner's Dive
Objective-C A Beginner's DiveAltece
 
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 6Dmitry Soshnikov
 
Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oopLearningTech
 
Extending Python - EuroPython 2014
Extending Python - EuroPython 2014Extending Python - EuroPython 2014
Extending Python - EuroPython 2014fcofdezc
 
Inheritance patterns
Inheritance patternsInheritance patterns
Inheritance patternsLuke Smith
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programmingjeffz
 
The promise of asynchronous PHP
The promise of asynchronous PHPThe promise of asynchronous PHP
The promise of asynchronous PHPWim Godden
 
Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Rafael 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 scripttimourian
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 

Tendances (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
 

En vedette

计算思维在儿童数字文化创作课程中的地位与培养
计算思维在儿童数字文化创作课程中的地位与培养计算思维在儿童数字文化创作课程中的地位与培养
计算思维在儿童数字文化创作课程中的地位与培养wikicn
 
Intro to Merb
Intro to MerbIntro to Merb
Intro to MerbMatt Todd
 
Building A Framework On Rack
Building A Framework On RackBuilding A Framework On Rack
Building A Framework On RackMatt Todd
 
儿童数字文化创作课程与信息技术课程的变革
儿童数字文化创作课程与信息技术课程的变革儿童数字文化创作课程与信息技术课程的变革
儿童数字文化创作课程与信息技术课程的变革wikicn
 
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 lociNTNU
 
Sgp Power Point 1st Submission
Sgp Power Point 1st SubmissionSgp Power Point 1st Submission
Sgp Power Point 1st SubmissionAliciaAnn1
 
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ónFátima Prieto
 

En vedette (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
 

Similaire à Ruby C Extensions Defines Classes

Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascriptMiao 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 Suckerockendude
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2drewz lin
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 
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)James Titcumb
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScriptDonald Sipe
 
Understanding PHP objects
Understanding PHP objectsUnderstanding PHP objects
Understanding PHP objectsjulien pauli
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
Class 3 - PHP Functions
Class 3 - PHP FunctionsClass 3 - PHP Functions
Class 3 - PHP FunctionsAhmed Swilam
 
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.docxjack60216
 

Similaire à Ruby C Extensions Defines Classes (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
 

Dernier

Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 

Dernier (20)

Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 

Ruby C Extensions Defines Classes

  • 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.