Ruby C extensions at the Ruby drink-up of Sophia, April 2012

R
C extensions easy in Ruby




                                       Apr 17th 2012
                                       Muriel Salvan
                  Open Source Lead developer and architect
                                       X-Aeon Solutions
                                         http://x-aeon.com
Why Ruby and C ?
Ruby without C
C without Ruby
Ruby and C combined
Ruby and C are
                   already coupled
Ruby core: around 100 classes written in
 C (String, Rational, Marshal, IO...)
Ruby standard libs: 35 libs written in C:
 (BigDecimal, Date, OpenSSL...)
Now You can write your
own C extensions easily
What is a C extension ?


A requirable library from Ruby code ...
 require 'myext'

… that can use any other Ruby's object
 or library,
… written in C,
… and compiled.
Technically speaking


A C extension is a compiled library (.so
 or .dll) that:
defines 1 specific C function,
is accessible in Ruby's load path (same
  as other .rb files)
It is used the same way Ruby's libraries
   (.rb) are (packaging, search path,
   require...)
What do you need to
             write C extensions ?

A C development environment ([g]cc, ld,
 [g]make...)
  Already installed on *nix
  Cygwin, MinGW, Ruby DevKit on Windows
Little C knowledge
Some Ruby's C API knowledge
How to write your C
    extension
Default Ruby program
            structure
myapp/
  bin/
    exec.rb
  lib/
    myapp/
       mylib.rb
  ext/
    myapp/
       myext.c
       extconf.rb
       myotherlib/
         otherlib.c
         extconf.rb
Write the C file
               ext/myapp/myext.c


#include "ruby.h"


void Init_myext() {
    printf("Hello Ruby from C!n");
}
Write the extconf file
              ext/myapp/extconf.rb


require 'mkmf'
create_makefile('myext')


And that's it!
Your C extension is ready to be compiled
 and used
How to compile and use
  your C extension
Compile it
                              in ext/myapp/
=> ruby extconf.rb
creating Makefile

          => ext/myapp/Makefile
=> make
gcc -I. -I/usr/lib/ruby/1.8/i386-cygwin
  -I/usr/lib/ruby/1.8/i386-cygwin -I.   -g -O2    -c
  myext.c
gcc -shared -s -o myext.so myext.o -L. -L/usr/lib -L.
  -Wl,--enable-auto-image-base,--enable-auto-import,--
  export-all   -lruby -ldl -lcrypt

          => ext/myapp/myext.so
Use it
                               bin/exec.rb
#!/bin/env ruby
puts 'Before requiring C extension'
require 'myapp/myext'
puts 'After requiring C extension'

=> ruby -Iext bin/exec.rb
Before requiring C extension
Hello Ruby from C!
After requiring C extension
And now, package it in a
    nice Ruby gem!
First flavor:
          Package the compiled
                      extension
Add the compiled extension to the files
 list (like any other library)
Add your ext/ directory as a required
 path
Don't forget to set your Gem platform as
 specific!
Platform dependent:
                              gem spec
                      myapp.compiled.gemspec.rb
Gem::Specification.new do |spec|
  spec.name = 'my_app_compiled'
  spec.version = '0.1'
  spec.summary = 'Summary'
  spec.author = 'me'
  spec.bindir = 'bin'
  spec.executable = 'exec.rb'
  spec.files = [ 'bin/exec.rb',
  'ext/myapp/myext.so' ]
  spec.platform = Gem::Platform::CURRENT
  spec.require_path = 'ext'
end
=> gem build myapp.compiled.gemspec.rb
  Successfully built RubyGem
  Name: my_app_compiled
  Version: 0.1
  File: my_app_compiled-0.1-x86-cygwin.gem
Platform dependent:
                 Install and run it
=> gem install my_app_compiled-0.1-x86-
  cygwin.gem
Successfully installed my_app_compiled-0.1-
  x86-cygwin
1 gem installed
Installing ri documentation for
  my_app_compiled-0.1-x86-cygwin...
Installing RDoc documentation for
  my_app_compiled-0.1-x86-cygwin...

=> exec.rb
Before requiring C extension
Hello Ruby from C!
After requiring C extension
Second flavor:
          Platform independent
                     packaging
Add the C extension source files to the
 files list
Add your ext/ directory as a required
 path
Keep your Gem platform as Ruby
Register the C extension (path to the
 extconf.rb file)
Platform independent:
                           gem spec
                    myapp.gemspec.rb
Gem::Specification.new do |spec|
  spec.name = 'my_app'
  # { ... }
  spec.executable = 'exec.rb'
   spec.files = [ 'bin/exec.rb',
   'ext/myapp/myext.c', 'ext/myapp/extconf.rb'
   ]
   spec.platform = Gem::Platform::RUBY
   spec.require_path = 'ext'
   spec.extensions =
   [ 'ext/myapp/extconf.rb' ]
end gem build myapp.gemspec.rb
=>
   Successfully built RubyGem
   Name: my_app
   Version: 0.1
   File: my_app-0.1.gem
Platform independent:
                Install and run it
=> gem install my_app-0.1.gem
Building native extensions. This could take
  a while...
Successfully installed my_app-0.1
1 gem installed
Installing ri documentation for my_app-0.1...
Installing RDoc documentation for
  my_app-0.1...

=> exec.rb
Before requiring C extension
Hello Ruby from C!
After requiring C extension
Which flavor the best ?

Platform dependent:   Platform independent:
Need to release 1     Need to release just 1
 Ruby gem per          Ruby gem
 platform (need to    Users must have a C
 compile on each       development
 platform)             environment to
Users do not need      install it
 any development
 environment
Need more than a Hello
      World ?
  => The Ruby C API
module MyModule
                  class MyClass
                    def my_method(param1, param2,
                  param3)
                    end
                  end
                end

static VALUE myclass_mymethod(
  VALUE rb_self,
  VALUE rb_param1,
  VALUE rb_param2,
  VALUE rb_param3) {
}

void Init_myext() {
  VALUE mymodule = rb_define_module("MyModule");
  VALUE myclass = rb_define_class_under(mymodule,
  "MyClass", rb_cObject);
  rb_define_method(myclass, "my_method",
  myclass_mymethod, 3);
}
if param1 == nil
                              puts 'Param1 is nil'
                              return nil
                            else
                              return param1 + 42
                            end




if (rb_param1 == Qnil) {
  rb_funcall(rb_self, rb_intern("puts"), 1,
  rb_str_new2("Param1 is nil"));
  return Qnil;
} else {
  int param1 = FIX2INT(rb_param1);
  VALUE result = INT2FIX(param1 + 42);
  return result;
}
param2.each do |elem|
                               elemstr = elem.to_s
                               elemstr[0] = 'A'
                               puts elemstr[0..3]
                             end



int nbrelems = RARRAY(rb_param2)->len;
int idx;
for (idx = 0; idx < nbrelems; ++idx) {
  VALUE rb_elem = rb_ary_entry(rb_param2, idx);
  VALUE rb_elemstr = rb_funcall(rb_elem,
  rb_intern("to_s"), 0);
  char* elemstr = RSTRING_PTR(rb_elemstr);
  elemstr[0] = 'A';
  char* substr = (char*)malloc(5);
  strncpy(substr, elemstr, 4);
  substr[4] = '0';
  rb_funcall(rb_self, rb_intern("puts"), 1,
  rb_str_new2(substr));
  free(substr);
}
param3.block_method(3) do |
                          block_param|
                          puts param1 + block_param
                        end


static VALUE call_block_method(VALUE rb_params) {
  VALUE rb_object = rb_ary_entry(rb_params, 0);
  VALUE rb_value = rb_ary_entry(rb_params, 1);
  return rb_funcall(rb_object, rb_intern("block_method"), 1, rb_value);
}

static VALUE yielded_block(VALUE rb_yield_params, VALUE
   rb_iterate_params) {
  VALUE rb_block_param = rb_yield_params;
  VALUE rb_self = rb_ary_entry(rb_iterate_params, 0);
  VALUE rb_param1 = rb_ary_entry(rb_iterate_params, 1);
  return rb_funcall(rb_self, rb_intern("puts"), 1,
   INT2FIX(FIX2INT(rb_block_param)+FIX2INT(rb_param1)));
}

rb_iterate(
  call_block_method,
  rb_ary_new3(2, rb_param3, INT2FIX(3)),
  yielded_block,
  rb_ary_new3(2, rb_self, rb_param1)
);
                                  Thanks Matz for Ruby!
Using external compiled
       libraries
      => FFI gem
FFI gem

 Import external functions from a
compiled library into a Ruby module

  require 'ffi'

  module MyLib
    extend FFI::Library
    ffi_lib 'c'
    attach_function :puts, [ :string ], :int
  end

  MyLib.puts 'Hello, World using libc!'
FFI features

It has a very intuitive DSL
It supports all C native types
It supports C structs (also nested),
   enums and global variables
It supports callbacks
It has smart methods to handle memory
   management of pointers and structs
Links

          Makefile generation options:
          Linuxtopia tutorial
          mkmf rdoc
          Ruby C API:
          Eqqon article
          Matz' Readme
          Metaprogramming
          FFI gem

This presentation is available under CC-BY license by Muriel Salvan
Q/A
1 of 35

Recommended

sl slides-unit-1.pptx by
sl slides-unit-1.pptxsl slides-unit-1.pptx
sl slides-unit-1.pptxSRAVANTHISALLARAM1
462 views166 slides
Session tracking in servlets by
Session tracking in servletsSession tracking in servlets
Session tracking in servletsvishal choudhary
388 views19 slides
NAT|PAT by
NAT|PATNAT|PAT
NAT|PATMao Mos!
19.2K views28 slides
Introduction to Web Services by
Introduction to Web ServicesIntroduction to Web Services
Introduction to Web ServicesThanachart Numnonda
7.3K views72 slides
Java essential notes by
Java essential notesJava essential notes
Java essential notesHabitamu Asimare
2.6K views87 slides
Php mysql ppt by
Php mysql pptPhp mysql ppt
Php mysql pptKarmatechnologies Pvt. Ltd.
70.1K views39 slides

More Related Content

What's hot

Swoogle by
SwoogleSwoogle
SwoogleSuchini Priyangika
1.2K views19 slides
Php and MySQL by
Php and MySQLPhp and MySQL
Php and MySQLTiji Thomas
29.5K views83 slides
Client side scripting by
Client side scriptingClient side scripting
Client side scriptingEleonora Ciceri
5.4K views106 slides
Etherchannel CCNA by
Etherchannel CCNAEtherchannel CCNA
Etherchannel CCNAJuan Zambrano Burgos
713 views6 slides
Risc y Cisc by
Risc y CiscRisc y Cisc
Risc y CiscGustavo Davila
29.1K views21 slides
Apuntes generación de codigo intermedio by
Apuntes generación de codigo intermedioApuntes generación de codigo intermedio
Apuntes generación de codigo intermedioHumano Terricola
1.4K views14 slides

What's hot(20)

Php and MySQL by Tiji Thomas
Php and MySQLPhp and MySQL
Php and MySQL
Tiji Thomas29.5K views
Apuntes generación de codigo intermedio by Humano Terricola
Apuntes generación de codigo intermedioApuntes generación de codigo intermedio
Apuntes generación de codigo intermedio
Humano Terricola1.4K views
Características MONGO DB by maxfontana90
Características MONGO DBCaracterísticas MONGO DB
Características MONGO DB
maxfontana9010.3K views
Asp.NET Validation controls by Guddu gupta
Asp.NET Validation controlsAsp.NET Validation controls
Asp.NET Validation controls
Guddu gupta7.7K views
Socket programming in Java (PPTX) by UC San Diego
Socket programming in Java (PPTX)Socket programming in Java (PPTX)
Socket programming in Java (PPTX)
UC San Diego3.2K views
JDBC,Types of JDBC,Resultset, statements,PreparedStatement,CallableStatements... by Pallepati Vasavi
JDBC,Types of JDBC,Resultset, statements,PreparedStatement,CallableStatements...JDBC,Types of JDBC,Resultset, statements,PreparedStatement,CallableStatements...
JDBC,Types of JDBC,Resultset, statements,PreparedStatement,CallableStatements...
Pallepati Vasavi4.6K views
Event In JavaScript by ShahDhruv21
Event In JavaScriptEvent In JavaScript
Event In JavaScript
ShahDhruv213.2K views
Create & Execute First Hadoop MapReduce Project in.pptx by vishal choudhary
Create & Execute First Hadoop MapReduce Project in.pptxCreate & Execute First Hadoop MapReduce Project in.pptx
Create & Execute First Hadoop MapReduce Project in.pptx
vishal choudhary129 views
REGULAR EXPRESSION TO N.F.A by Dev Ashish
REGULAR EXPRESSION TO N.F.AREGULAR EXPRESSION TO N.F.A
REGULAR EXPRESSION TO N.F.A
Dev Ashish4K views
Procedures functions structures in VB.Net by tjunicornfx
Procedures  functions  structures in VB.NetProcedures  functions  structures in VB.Net
Procedures functions structures in VB.Net
tjunicornfx7.1K views
Conceptos Unidad 1 Lenguajes Automatas Introducción a la Teoría de Lenguaje... by Hugo Alberto Rivera Diaz
Conceptos Unidad 1 Lenguajes Automatas Introducción  a  la Teoría de Lenguaje...Conceptos Unidad 1 Lenguajes Automatas Introducción  a  la Teoría de Lenguaje...
Conceptos Unidad 1 Lenguajes Automatas Introducción a la Teoría de Lenguaje...
Lecture 10 semantic analysis 01 by Iffat Anjum
Lecture 10 semantic analysis 01Lecture 10 semantic analysis 01
Lecture 10 semantic analysis 01
Iffat Anjum5K views

Viewers also liked

Ruby and Docker on Rails by
Ruby and Docker on RailsRuby and Docker on Rails
Ruby and Docker on RailsMuriel Salvan
6.3K views62 slides
Pry at the Ruby Drink-up of Sophia, February 2012 by
Pry at the Ruby Drink-up of Sophia, February 2012Pry at the Ruby Drink-up of Sophia, February 2012
Pry at the Ruby Drink-up of Sophia, February 2012rivierarb
1.5K views13 slides
Ruby 2.0 at the Ruby drink-up of Sophia, February 2013 by
Ruby 2.0 at the Ruby drink-up of Sophia, February 2013Ruby 2.0 at the Ruby drink-up of Sophia, February 2013
Ruby 2.0 at the Ruby drink-up of Sophia, February 2013rivierarb
1.3K views15 slides
Ruby and Twitter at the Ruby drink-up of Sophia, January 2013 by
Ruby and Twitter at the Ruby drink-up of Sophia, January 2013Ruby and Twitter at the Ruby drink-up of Sophia, January 2013
Ruby and Twitter at the Ruby drink-up of Sophia, January 2013rivierarb
1.5K views11 slides
Ruby object model at the Ruby drink-up of Sophia, January 2013 by
Ruby object model at the Ruby drink-up of Sophia, January 2013Ruby object model at the Ruby drink-up of Sophia, January 2013
Ruby object model at the Ruby drink-up of Sophia, January 2013rivierarb
1.4K views23 slides
Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012 by
Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012
Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012rivierarb
1.8K views23 slides

Viewers also liked(10)

Ruby and Docker on Rails by Muriel Salvan
Ruby and Docker on RailsRuby and Docker on Rails
Ruby and Docker on Rails
Muriel Salvan6.3K views
Pry at the Ruby Drink-up of Sophia, February 2012 by rivierarb
Pry at the Ruby Drink-up of Sophia, February 2012Pry at the Ruby Drink-up of Sophia, February 2012
Pry at the Ruby Drink-up of Sophia, February 2012
rivierarb1.5K views
Ruby 2.0 at the Ruby drink-up of Sophia, February 2013 by rivierarb
Ruby 2.0 at the Ruby drink-up of Sophia, February 2013Ruby 2.0 at the Ruby drink-up of Sophia, February 2013
Ruby 2.0 at the Ruby drink-up of Sophia, February 2013
rivierarb1.3K views
Ruby and Twitter at the Ruby drink-up of Sophia, January 2013 by rivierarb
Ruby and Twitter at the Ruby drink-up of Sophia, January 2013Ruby and Twitter at the Ruby drink-up of Sophia, January 2013
Ruby and Twitter at the Ruby drink-up of Sophia, January 2013
rivierarb1.5K views
Ruby object model at the Ruby drink-up of Sophia, January 2013 by rivierarb
Ruby object model at the Ruby drink-up of Sophia, January 2013Ruby object model at the Ruby drink-up of Sophia, January 2013
Ruby object model at the Ruby drink-up of Sophia, January 2013
rivierarb1.4K views
Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012 by rivierarb
Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012
Piloting processes through std IO at the Ruby Drink-up of Sophia, January 2012
rivierarb1.8K views
DRb at the Ruby Drink-up of Sophia, December 2011 by rivierarb
DRb at the Ruby Drink-up of Sophia, December 2011DRb at the Ruby Drink-up of Sophia, December 2011
DRb at the Ruby Drink-up of Sophia, December 2011
rivierarb1.2K views
Quines—Programming your way back to where you were by Jean-Baptiste Mazon
Quines—Programming your way back to where you wereQuines—Programming your way back to where you were
Quines—Programming your way back to where you were

Similar to Ruby C extensions at the Ruby drink-up of Sophia, April 2012

Writing a Gem with native extensions by
Writing a Gem with native extensionsWriting a Gem with native extensions
Writing a Gem with native extensionsTristan Penman
187 views27 slides
Introduction to Rails - presented by Arman Ortega by
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortegaarman o
523 views52 slides
Mac ruby deployment by
Mac ruby deploymentMac ruby deployment
Mac ruby deploymentThilo Utke
2.7K views70 slides
Toolbox of a Ruby Team by
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
422 views38 slides
Rails web api 开发 by
Rails web api 开发Rails web api 开发
Rails web api 开发shaokun
1.3K views45 slides
Extending Ruby using C++ by
Extending Ruby using C++Extending Ruby using C++
Extending Ruby using C++Tristan Penman
454 views24 slides

Similar to Ruby C extensions at the Ruby drink-up of Sophia, April 2012(20)

Writing a Gem with native extensions by Tristan Penman
Writing a Gem with native extensionsWriting a Gem with native extensions
Writing a Gem with native extensions
Tristan Penman187 views
Introduction to Rails - presented by Arman Ortega by arman o
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
arman o523 views
Mac ruby deployment by Thilo Utke
Mac ruby deploymentMac ruby deployment
Mac ruby deployment
Thilo Utke2.7K views
Toolbox of a Ruby Team by Arto Artnik
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
Arto Artnik422 views
Rails web api 开发 by shaokun
Rails web api 开发Rails web api 开发
Rails web api 开发
shaokun1.3K views
Infrastructure as code - Python Saati #36 by Halil Kaya
Infrastructure as code - Python Saati #36Infrastructure as code - Python Saati #36
Infrastructure as code - Python Saati #36
Halil Kaya272 views
A tour on ruby and friends by 旻琦 潘
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘936 views
Infrastructureascode slideshare-160331143725 by miguel dominguez
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
miguel dominguez53 views
Infrastructureascode slideshare-160331143725 by MortazaJohari
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
MortazaJohari25 views
Infrastructure as code: running microservices on AWS using Docker, Terraform,... by Yevgeniy Brikman
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Yevgeniy Brikman177.5K views
What lies beneath the beautiful code? by Niranjan Sarade
What lies beneath the beautiful code?What lies beneath the beautiful code?
What lies beneath the beautiful code?
Niranjan Sarade3.7K views
Building web framework with Rack by sickill
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill3.6K views
Middleware as Code with mruby by Hiroshi SHIBATA
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mruby
Hiroshi SHIBATA5.2K views
Rails Engine | Modular application by mirrec
Rails Engine | Modular applicationRails Engine | Modular application
Rails Engine | Modular application
mirrec6.3K views
What's new and great in Rails 3 - Matt Gauger - Milwaukee Ruby Users Group De... by Matt Gauger
What's new and great in Rails 3 - Matt Gauger - Milwaukee Ruby Users Group De...What's new and great in Rails 3 - Matt Gauger - Milwaukee Ruby Users Group De...
What's new and great in Rails 3 - Matt Gauger - Milwaukee Ruby Users Group De...
Matt Gauger1.9K views

Recently uploaded

【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院 by
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院IttrainingIttraining
69 views8 slides
Melek BEN MAHMOUD.pdf by
Melek BEN MAHMOUD.pdfMelek BEN MAHMOUD.pdf
Melek BEN MAHMOUD.pdfMelekBenMahmoud
17 views1 slide
Business Analyst Series 2023 - Week 3 Session 5 by
Business Analyst Series 2023 -  Week 3 Session 5Business Analyst Series 2023 -  Week 3 Session 5
Business Analyst Series 2023 - Week 3 Session 5DianaGray10
345 views20 slides
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading... by
Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading...The Digital Insurer
24 views52 slides
PharoJS - Zürich Smalltalk Group Meetup November 2023 by
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023Noury Bouraqadi
139 views17 slides
TouchLog: Finger Micro Gesture Recognition Using Photo-Reflective Sensors by
TouchLog: Finger Micro Gesture Recognition  Using Photo-Reflective SensorsTouchLog: Finger Micro Gesture Recognition  Using Photo-Reflective Sensors
TouchLog: Finger Micro Gesture Recognition Using Photo-Reflective Sensorssugiuralab
23 views15 slides

Recently uploaded(20)

【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院 by IttrainingIttraining
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院
Business Analyst Series 2023 - Week 3 Session 5 by DianaGray10
Business Analyst Series 2023 -  Week 3 Session 5Business Analyst Series 2023 -  Week 3 Session 5
Business Analyst Series 2023 - Week 3 Session 5
DianaGray10345 views
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading... by The Digital Insurer
Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading...
PharoJS - Zürich Smalltalk Group Meetup November 2023 by Noury Bouraqadi
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023
Noury Bouraqadi139 views
TouchLog: Finger Micro Gesture Recognition Using Photo-Reflective Sensors by sugiuralab
TouchLog: Finger Micro Gesture Recognition  Using Photo-Reflective SensorsTouchLog: Finger Micro Gesture Recognition  Using Photo-Reflective Sensors
TouchLog: Finger Micro Gesture Recognition Using Photo-Reflective Sensors
sugiuralab23 views
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive by Network Automation Forum
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLiveAutomating a World-Class Technology Conference; Behind the Scenes of CiscoLive
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays33 views
Future of AR - Facebook Presentation by Rob McCarty
Future of AR - Facebook PresentationFuture of AR - Facebook Presentation
Future of AR - Facebook Presentation
Rob McCarty22 views
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N... by James Anderson
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
James Anderson126 views
Special_edition_innovator_2023.pdf by WillDavies22
Special_edition_innovator_2023.pdfSpecial_edition_innovator_2023.pdf
Special_edition_innovator_2023.pdf
WillDavies2218 views
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ... by Jasper Oosterveld
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas... by Bernd Ruecker
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
Bernd Ruecker48 views
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf by Dr. Jimmy Schwarzkopf
STKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdfSTKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdf
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf

Ruby C extensions at the Ruby drink-up of Sophia, April 2012

  • 1. C extensions easy in Ruby Apr 17th 2012 Muriel Salvan Open Source Lead developer and architect X-Aeon Solutions http://x-aeon.com
  • 5. Ruby and C combined
  • 6. Ruby and C are already coupled Ruby core: around 100 classes written in C (String, Rational, Marshal, IO...) Ruby standard libs: 35 libs written in C: (BigDecimal, Date, OpenSSL...)
  • 7. Now You can write your own C extensions easily
  • 8. What is a C extension ? A requirable library from Ruby code ... require 'myext' … that can use any other Ruby's object or library, … written in C, … and compiled.
  • 9. Technically speaking A C extension is a compiled library (.so or .dll) that: defines 1 specific C function, is accessible in Ruby's load path (same as other .rb files) It is used the same way Ruby's libraries (.rb) are (packaging, search path, require...)
  • 10. What do you need to write C extensions ? A C development environment ([g]cc, ld, [g]make...) Already installed on *nix Cygwin, MinGW, Ruby DevKit on Windows Little C knowledge Some Ruby's C API knowledge
  • 11. How to write your C extension
  • 12. Default Ruby program structure myapp/ bin/ exec.rb lib/ myapp/ mylib.rb ext/ myapp/ myext.c extconf.rb myotherlib/ otherlib.c extconf.rb
  • 13. Write the C file ext/myapp/myext.c #include "ruby.h" void Init_myext() { printf("Hello Ruby from C!n"); }
  • 14. Write the extconf file ext/myapp/extconf.rb require 'mkmf' create_makefile('myext') And that's it! Your C extension is ready to be compiled and used
  • 15. How to compile and use your C extension
  • 16. Compile it in ext/myapp/ => ruby extconf.rb creating Makefile => ext/myapp/Makefile => make gcc -I. -I/usr/lib/ruby/1.8/i386-cygwin -I/usr/lib/ruby/1.8/i386-cygwin -I. -g -O2 -c myext.c gcc -shared -s -o myext.so myext.o -L. -L/usr/lib -L. -Wl,--enable-auto-image-base,--enable-auto-import,-- export-all -lruby -ldl -lcrypt => ext/myapp/myext.so
  • 17. Use it bin/exec.rb #!/bin/env ruby puts 'Before requiring C extension' require 'myapp/myext' puts 'After requiring C extension' => ruby -Iext bin/exec.rb Before requiring C extension Hello Ruby from C! After requiring C extension
  • 18. And now, package it in a nice Ruby gem!
  • 19. First flavor: Package the compiled extension Add the compiled extension to the files list (like any other library) Add your ext/ directory as a required path Don't forget to set your Gem platform as specific!
  • 20. Platform dependent: gem spec myapp.compiled.gemspec.rb Gem::Specification.new do |spec| spec.name = 'my_app_compiled' spec.version = '0.1' spec.summary = 'Summary' spec.author = 'me' spec.bindir = 'bin' spec.executable = 'exec.rb' spec.files = [ 'bin/exec.rb', 'ext/myapp/myext.so' ] spec.platform = Gem::Platform::CURRENT spec.require_path = 'ext' end => gem build myapp.compiled.gemspec.rb Successfully built RubyGem Name: my_app_compiled Version: 0.1 File: my_app_compiled-0.1-x86-cygwin.gem
  • 21. Platform dependent: Install and run it => gem install my_app_compiled-0.1-x86- cygwin.gem Successfully installed my_app_compiled-0.1- x86-cygwin 1 gem installed Installing ri documentation for my_app_compiled-0.1-x86-cygwin... Installing RDoc documentation for my_app_compiled-0.1-x86-cygwin... => exec.rb Before requiring C extension Hello Ruby from C! After requiring C extension
  • 22. Second flavor: Platform independent packaging Add the C extension source files to the files list Add your ext/ directory as a required path Keep your Gem platform as Ruby Register the C extension (path to the extconf.rb file)
  • 23. Platform independent: gem spec myapp.gemspec.rb Gem::Specification.new do |spec| spec.name = 'my_app' # { ... } spec.executable = 'exec.rb' spec.files = [ 'bin/exec.rb', 'ext/myapp/myext.c', 'ext/myapp/extconf.rb' ] spec.platform = Gem::Platform::RUBY spec.require_path = 'ext' spec.extensions = [ 'ext/myapp/extconf.rb' ] end gem build myapp.gemspec.rb => Successfully built RubyGem Name: my_app Version: 0.1 File: my_app-0.1.gem
  • 24. Platform independent: Install and run it => gem install my_app-0.1.gem Building native extensions. This could take a while... Successfully installed my_app-0.1 1 gem installed Installing ri documentation for my_app-0.1... Installing RDoc documentation for my_app-0.1... => exec.rb Before requiring C extension Hello Ruby from C! After requiring C extension
  • 25. Which flavor the best ? Platform dependent: Platform independent: Need to release 1 Need to release just 1 Ruby gem per Ruby gem platform (need to Users must have a C compile on each development platform) environment to Users do not need install it any development environment
  • 26. Need more than a Hello World ? => The Ruby C API
  • 27. module MyModule class MyClass def my_method(param1, param2, param3) end end end static VALUE myclass_mymethod( VALUE rb_self, VALUE rb_param1, VALUE rb_param2, VALUE rb_param3) { } void Init_myext() { VALUE mymodule = rb_define_module("MyModule"); VALUE myclass = rb_define_class_under(mymodule, "MyClass", rb_cObject); rb_define_method(myclass, "my_method", myclass_mymethod, 3); }
  • 28. if param1 == nil puts 'Param1 is nil' return nil else return param1 + 42 end if (rb_param1 == Qnil) { rb_funcall(rb_self, rb_intern("puts"), 1, rb_str_new2("Param1 is nil")); return Qnil; } else { int param1 = FIX2INT(rb_param1); VALUE result = INT2FIX(param1 + 42); return result; }
  • 29. param2.each do |elem| elemstr = elem.to_s elemstr[0] = 'A' puts elemstr[0..3] end int nbrelems = RARRAY(rb_param2)->len; int idx; for (idx = 0; idx < nbrelems; ++idx) { VALUE rb_elem = rb_ary_entry(rb_param2, idx); VALUE rb_elemstr = rb_funcall(rb_elem, rb_intern("to_s"), 0); char* elemstr = RSTRING_PTR(rb_elemstr); elemstr[0] = 'A'; char* substr = (char*)malloc(5); strncpy(substr, elemstr, 4); substr[4] = '0'; rb_funcall(rb_self, rb_intern("puts"), 1, rb_str_new2(substr)); free(substr); }
  • 30. param3.block_method(3) do | block_param| puts param1 + block_param end static VALUE call_block_method(VALUE rb_params) { VALUE rb_object = rb_ary_entry(rb_params, 0); VALUE rb_value = rb_ary_entry(rb_params, 1); return rb_funcall(rb_object, rb_intern("block_method"), 1, rb_value); } static VALUE yielded_block(VALUE rb_yield_params, VALUE rb_iterate_params) { VALUE rb_block_param = rb_yield_params; VALUE rb_self = rb_ary_entry(rb_iterate_params, 0); VALUE rb_param1 = rb_ary_entry(rb_iterate_params, 1); return rb_funcall(rb_self, rb_intern("puts"), 1, INT2FIX(FIX2INT(rb_block_param)+FIX2INT(rb_param1))); } rb_iterate( call_block_method, rb_ary_new3(2, rb_param3, INT2FIX(3)), yielded_block, rb_ary_new3(2, rb_self, rb_param1) ); Thanks Matz for Ruby!
  • 31. Using external compiled libraries => FFI gem
  • 32. FFI gem Import external functions from a compiled library into a Ruby module require 'ffi' module MyLib extend FFI::Library ffi_lib 'c' attach_function :puts, [ :string ], :int end MyLib.puts 'Hello, World using libc!'
  • 33. FFI features It has a very intuitive DSL It supports all C native types It supports C structs (also nested), enums and global variables It supports callbacks It has smart methods to handle memory management of pointers and structs
  • 34. Links Makefile generation options: Linuxtopia tutorial mkmf rdoc Ruby C API: Eqqon article Matz' Readme Metaprogramming FFI gem This presentation is available under CC-BY license by Muriel Salvan
  • 35. Q/A