SlideShare a Scribd company logo
Extending Ruby using C++
Tristan Penman
Melbourne C++ Meetup, September 2018
Ruby essentials
What is Ruby?
 Ruby is a dynamically-typed, object-oriented language
 Garbage collection built into the VM
 Several implementations exist
 MRI – Matz's Ruby Interpreter (a.k.a. CRuby)
 JRuby – JVM based implementation
 Rubinius – Implemented in C++ and Ruby
 Ruby libraries are typically packaged as Gems
 Gems that need to use C or C++ typically do so via native
extensions
Ruby essentials
class Person
attr_reader :name, :age
def initialize(name, age) # constructor
@name, @age =name, age
end
def <=>(person) #the comparison operator for sorting
@age <=> person.age
end
def to_s #returns string representation of Person
"#{@name} (#{@age})"
end
end
Example code (1/2)
Ruby essentials
Example code (2/2)
#continued fromprevious slide
group=[
Person.new("Bob", 33),
Person.new("Chris", 16),
Person.new("Ash", 23)
]
puts group.sort.reverse
Bob(33)
Ash (23)
Chris(16)
Expected output:
Ruby essentials
Popular gems with native extensions
• Byebug - a debugger for Ruby, that uses Ruby's TracePoint API
for execution control and the Debug Inspector API for call
stack navigation. Written as a C extension for speed.
• nokogiri - an HTML and XML parser. Uses native libraries for
speed and ensure standards compliance.
• RMagick - bindings for the ImageMagick image manipulation
library.
• sqlite3 - bindings for the SQLite3 database engine.
Ruby essentials
Installing gems
$ gem install <gem_name>
To install the 'ffi' gem, which we'll use in the first example:
$ gem install ffi
This gem includes native extensions, so output will look like:
Fetching: ffi-1.9.25.gem (100%)
Building native extensions. Thiscould take a while...
Successfully installed ffi-1.9.25
Parsing documentation forffi-1.9.25
Installing ridocumentation forffi-1.9.25
Done installing documentation for ffi after 27 seconds
1 gem installed
Options for extending Ruby
• Foreign function interface
– Technique for accessing shared libraries that follow C-style
calling convention
• Inlined C / C++ code
– Compiles native code at runtime
• Native extensions with C and C++
– Precompiled
• All example code is available at:
https://github.com/tristanpenman/ruby-cpp-examples
Foreign function interface
require 'ffi'
module Simon
#Include ffi functionality as a 'mixin'
extend FFI::Library
#Link with libc
ffi_lib 'c'
#Define afunction that takes astring (char *) andprints it
attach_function :says, :puts, [:string ],:int
end
Simon.says 'Hello'
simon_ffi.rb
Foreign function interface
Limitations
• Generally requires that code is available as a shared library on
the user's operating system
• That library needs to export an API that follow the C-style
calling convention (__cdecl)
• Link errors may occur at runtime, rather than when a gem is
first installed
• In the simple case, 'ffi' gem defines methods as belonging to a
Ruby module
– Not appropriate for exposing C++ classes in Ruby
Inlined C / C++ code
require 'inline'
module Simon
inline(:C) do |builder|
builder.add_compile_flags'-xc++', '-lstdc++'
builder.include '<iostream>'
builder.c_singleton '
void says(const char *str) {
std::cout <<str <<std::endl;
}'
end
end
Simon.says 'Hello'
simon_inline.rb
Inlined C++ code
Limitations
• Incurs runtime compile overhead
• Semantics of RubyInline gem are a bit tricky
– Moving beyond defining individual methods becomes
much more complicated
– Best documentation for this happens to 'inline.rb' in the
RubyInline source code
Native extensions
• Address some of the limitations of FFI and inline C++ code
techniques
• Compiled prior to runtime, but they are generally subject to
rigorous runtime requirements
• Typically implemented using the Ruby C API
• Our simple example requires two files:
– simon_native.c, which contains the implementation code
– extconf.rb, to generate a Makefile
• simon_native.c must include Init_simon_native(), which is
called by the Ruby VM to load the extension
Native extensions
#include <ruby.h>
#include <stdio.h>
VALUE says(VALUE _self, VALUE str) {
Check_Type(str, T_STRING);
puts(StringValueCStr(str));
return Qnil;
}
voidInit_simon_native() {
VALUE mod=rb_define_module("Simon");
const intnum_args =1;
rb_define_module_function(mod, "says", says, num_args);
}
simon_native.c
Native extensions
require 'mkmf'
#Generates aMakefile tocompile simon_native.c intoa bundle
#that can be loaded intoa Ruby VM
create_makefile 'simon_native'
extconf.rb
Running 'make' should generate a bundle that can be loaded into
your Ruby program like so:
require './simon_native'
Simon.says 'Hello'
Hello
Native extensions
Limitations
• Requires code to be written in C
– Assumptions around considerations such as file extensions
• Uses Ruby C API, which is not terribly user friendly
• What about C++?
Native extensions with C++
Using the 'rice' gem
• Rice is a C++ wrapper for Ruby's C API
• Provides classes and templates that make the Ruby API easier
and safer to use
• Also provides template functions that can take an existing C++
class and make it available to Ruby code
• Minor changes to extconf.rb are required
Native extensions with C++
simon_native_rice.cpp
#include <iostream>
#include "rice/Module.hpp"
using namespace Rice;
void says(const char *str) {
std::cout <<str << std::endl;
}
extern "C"
voidInit_simon_native_rice() {
define_module("Simon")
.define_module_function("says", &says);
}
Native extensions with C++
extconf.rb
require 'mkmf-rice'
#Assumes the presence ofa file named 'simon_native_rice.cpp'
create_makefile 'simon_native_rice'
Native extensions with C++
Wrapping C++ classes
• Say we have an existing C++ class that we want to make
accessible via Ruby
• Declared in simon.hpp:
#pragmaonce
#include <iostream>
class Simon {
void says(const char * str) {
std::cout <<str << std::endl;
}
}
Wrapping C++ classes
simon_native_rice_wrapper.cpp
#include "rice/Constructor.hpp"
#include "rice/Data_Type.hpp"
#include "simon.hpp"
using namespace Rice;
extern "C"
voidInit_simon_native_rice_wrapper() {
Data_Type<Simon> rb_cSimon =
define_class<Simon>("Simon")
.define_constructor(Constructor<Simon>())
.define_method("says", &Simon::says);
}
Native extensions with C++
extconf.rb
require 'mkmf-rice' #instead of'mkmf'
create_makefile 'simon_native_rice_wrapper'
require './simon_native_rice_wrapper'
simon =Simon.new
simon.says 'Hello'
After running 'make', usage is similar to the example for the
'RubyInline' gem:
Resources
• Core documentation:
https://ruby-doc.org/core-
2.3.3/doc/extension_rdoc.html
(Beware the version number in this link)
• Aaron Bedra's Extending Ruby guide
http://aaronbedra.com/extending-ruby
• Pat Shaughnessy’s book:
Ruby Under a Microscope
Resources
• IBM's Building Ruby extensions in C++ using Rice
https://www.ibm.com/developerworks/library/os-
extendruby/index.html
• Chris Lalancette's in-depth series on writing Ruby extensions
in C, which covers numerous topics:
http://clalance.blogspot.com/2011/01/writing-ruby-
extensions-in-c-part-1.html
Thanks for listening

More Related Content

What's hot (20)

PDF
Introduction to Hibernate Framework
Mohit Kanwar
 
PPTX
Java Lambda Expressions.pptx
SameerAhmed593310
 
PDF
Java 8 lambda expressions
Logan Chien
 
PPTX
SOLID principles
Jonathan Holloway
 
PDF
JPA and Hibernate
elliando dias
 
PDF
Presentation aix performance updates & issues
xKinAnx
 
PDF
What Is Spring Framework In Java | Spring Framework Tutorial For Beginners Wi...
Edureka!
 
PPT
Ocl
Rajesh Kumar
 
PPTX
java 8 new features
Rohit Verma
 
PPT
Spring Core
Pushan Bhattacharya
 
PPTX
Boost your productivity with Scala tooling!
MeriamLachkar1
 
ODP
Ruby
Aizat Faiz
 
PPTX
Spring framework Controllers and Annotations
Anuj Singh Rajput
 
PPTX
Java 8 - Features Overview
Sergii Stets
 
PPTX
New Features in JDK 8
Martin Toshev
 
PDF
CQ5 QueryBuilder - .adaptTo(Berlin) 2011
Alexander Klimetschek
 
PPTX
PHP Basics
Saraswathi Murugan
 
PPT
Scanner class
M Vishnuvardhan Reddy
 
PDF
Qemu Introduction
Chiawei Wang
 
Introduction to Hibernate Framework
Mohit Kanwar
 
Java Lambda Expressions.pptx
SameerAhmed593310
 
Java 8 lambda expressions
Logan Chien
 
SOLID principles
Jonathan Holloway
 
JPA and Hibernate
elliando dias
 
Presentation aix performance updates & issues
xKinAnx
 
What Is Spring Framework In Java | Spring Framework Tutorial For Beginners Wi...
Edureka!
 
java 8 new features
Rohit Verma
 
Spring Core
Pushan Bhattacharya
 
Boost your productivity with Scala tooling!
MeriamLachkar1
 
Spring framework Controllers and Annotations
Anuj Singh Rajput
 
Java 8 - Features Overview
Sergii Stets
 
New Features in JDK 8
Martin Toshev
 
CQ5 QueryBuilder - .adaptTo(Berlin) 2011
Alexander Klimetschek
 
PHP Basics
Saraswathi Murugan
 
Scanner class
M Vishnuvardhan Reddy
 
Qemu Introduction
Chiawei Wang
 

Similar to Extending Ruby using C++ (20)

PPTX
Introduction to Ruby Native Extensions and Foreign Function Interface
Oleksii Sukhovii
 
ODP
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
rivierarb
 
PPTX
Writing a Gem with native extensions
Tristan Penman
 
PDF
Ruby confhighlights
Claire Tran
 
PDF
How to write Ruby extensions with Crystal
Anna (gaar4ica) Shcherbinina
 
PPTX
sl-unit2 ppt for cse in b.tech jntuh iii year
UdayKumar693239
 
PDF
MacRuby & HotCocoa
Thilo Utke
 
PPT
GEM - GNU C Compiler Extensions Framework
Alexey Smirnov
 
PDF
GNU Compiler Collection - August 2005
Saleem Ansari
 
KEY
Ruby FFI
delagoya
 
PDF
The details of CI/CD environment for Ruby
Hiroshi SHIBATA
 
PDF
JRuby: The Hard Parts
Charles Nutter
 
PDF
Moving from C++ to Ruby
Leslie Brown
 
PDF
Gitlab - Creating C++ applications with Gitlab CI
Uilian Ries
 
PPT
Ruby Projects and Libraries
Vorleak Chy
 
PDF
Rubinius - A Tool of the Future
evanphx
 
PDF
Intro to C++ - language
Jussi Pohjolainen
 
PDF
Ola Bini J Ruby Power On The Jvm
deimos
 
PDF
ruby-cocoa
tutorialsruby
 
PDF
ruby-cocoa
tutorialsruby
 
Introduction to Ruby Native Extensions and Foreign Function Interface
Oleksii Sukhovii
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
rivierarb
 
Writing a Gem with native extensions
Tristan Penman
 
Ruby confhighlights
Claire Tran
 
How to write Ruby extensions with Crystal
Anna (gaar4ica) Shcherbinina
 
sl-unit2 ppt for cse in b.tech jntuh iii year
UdayKumar693239
 
MacRuby & HotCocoa
Thilo Utke
 
GEM - GNU C Compiler Extensions Framework
Alexey Smirnov
 
GNU Compiler Collection - August 2005
Saleem Ansari
 
Ruby FFI
delagoya
 
The details of CI/CD environment for Ruby
Hiroshi SHIBATA
 
JRuby: The Hard Parts
Charles Nutter
 
Moving from C++ to Ruby
Leslie Brown
 
Gitlab - Creating C++ applications with Gitlab CI
Uilian Ries
 
Ruby Projects and Libraries
Vorleak Chy
 
Rubinius - A Tool of the Future
evanphx
 
Intro to C++ - language
Jussi Pohjolainen
 
Ola Bini J Ruby Power On The Jvm
deimos
 
ruby-cocoa
tutorialsruby
 
ruby-cocoa
tutorialsruby
 
Ad

Recently uploaded (20)

PPTX
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
PPTX
In From the Cold: Open Source as Part of Mainstream Software Asset Management
Shane Coughlan
 
PDF
How to Hire AI Developers_ Step-by-Step Guide in 2025.pdf
DianApps Technologies
 
PPTX
Finding Your License Details in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
PPTX
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
PDF
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
PPTX
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
PDF
MiniTool Partition Wizard Free Crack + Full Free Download 2025
bashirkhan333g
 
PDF
Driver Easy Pro 6.1.1 Crack Licensce key 2025 FREE
utfefguu
 
PDF
Top Agile Project Management Tools for Teams in 2025
Orangescrum
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PDF
Build It, Buy It, or Already Got It? Make Smarter Martech Decisions
bbedford2
 
PDF
The 5 Reasons for IT Maintenance - Arna Softech
Arna Softech
 
PPTX
Milwaukee Marketo User Group - Summer Road Trip: Mapping and Personalizing Yo...
bbedford2
 
PDF
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PDF
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
PPTX
Agentic Automation Journey Session 1/5: Context Grounding and Autopilot for E...
klpathrudu
 
PPTX
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
In From the Cold: Open Source as Part of Mainstream Software Asset Management
Shane Coughlan
 
How to Hire AI Developers_ Step-by-Step Guide in 2025.pdf
DianApps Technologies
 
Finding Your License Details in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
MiniTool Partition Wizard Free Crack + Full Free Download 2025
bashirkhan333g
 
Driver Easy Pro 6.1.1 Crack Licensce key 2025 FREE
utfefguu
 
Top Agile Project Management Tools for Teams in 2025
Orangescrum
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
Build It, Buy It, or Already Got It? Make Smarter Martech Decisions
bbedford2
 
The 5 Reasons for IT Maintenance - Arna Softech
Arna Softech
 
Milwaukee Marketo User Group - Summer Road Trip: Mapping and Personalizing Yo...
bbedford2
 
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
Agentic Automation Journey Session 1/5: Context Grounding and Autopilot for E...
klpathrudu
 
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Ad

Extending Ruby using C++

  • 1. Extending Ruby using C++ Tristan Penman Melbourne C++ Meetup, September 2018
  • 2. Ruby essentials What is Ruby?  Ruby is a dynamically-typed, object-oriented language  Garbage collection built into the VM  Several implementations exist  MRI – Matz's Ruby Interpreter (a.k.a. CRuby)  JRuby – JVM based implementation  Rubinius – Implemented in C++ and Ruby  Ruby libraries are typically packaged as Gems  Gems that need to use C or C++ typically do so via native extensions
  • 3. Ruby essentials class Person attr_reader :name, :age def initialize(name, age) # constructor @name, @age =name, age end def <=>(person) #the comparison operator for sorting @age <=> person.age end def to_s #returns string representation of Person "#{@name} (#{@age})" end end Example code (1/2)
  • 4. Ruby essentials Example code (2/2) #continued fromprevious slide group=[ Person.new("Bob", 33), Person.new("Chris", 16), Person.new("Ash", 23) ] puts group.sort.reverse Bob(33) Ash (23) Chris(16) Expected output:
  • 5. Ruby essentials Popular gems with native extensions • Byebug - a debugger for Ruby, that uses Ruby's TracePoint API for execution control and the Debug Inspector API for call stack navigation. Written as a C extension for speed. • nokogiri - an HTML and XML parser. Uses native libraries for speed and ensure standards compliance. • RMagick - bindings for the ImageMagick image manipulation library. • sqlite3 - bindings for the SQLite3 database engine.
  • 6. Ruby essentials Installing gems $ gem install <gem_name> To install the 'ffi' gem, which we'll use in the first example: $ gem install ffi This gem includes native extensions, so output will look like: Fetching: ffi-1.9.25.gem (100%) Building native extensions. Thiscould take a while... Successfully installed ffi-1.9.25 Parsing documentation forffi-1.9.25 Installing ridocumentation forffi-1.9.25 Done installing documentation for ffi after 27 seconds 1 gem installed
  • 7. Options for extending Ruby • Foreign function interface – Technique for accessing shared libraries that follow C-style calling convention • Inlined C / C++ code – Compiles native code at runtime • Native extensions with C and C++ – Precompiled • All example code is available at: https://github.com/tristanpenman/ruby-cpp-examples
  • 8. Foreign function interface require 'ffi' module Simon #Include ffi functionality as a 'mixin' extend FFI::Library #Link with libc ffi_lib 'c' #Define afunction that takes astring (char *) andprints it attach_function :says, :puts, [:string ],:int end Simon.says 'Hello' simon_ffi.rb
  • 9. Foreign function interface Limitations • Generally requires that code is available as a shared library on the user's operating system • That library needs to export an API that follow the C-style calling convention (__cdecl) • Link errors may occur at runtime, rather than when a gem is first installed • In the simple case, 'ffi' gem defines methods as belonging to a Ruby module – Not appropriate for exposing C++ classes in Ruby
  • 10. Inlined C / C++ code require 'inline' module Simon inline(:C) do |builder| builder.add_compile_flags'-xc++', '-lstdc++' builder.include '<iostream>' builder.c_singleton ' void says(const char *str) { std::cout <<str <<std::endl; }' end end Simon.says 'Hello' simon_inline.rb
  • 11. Inlined C++ code Limitations • Incurs runtime compile overhead • Semantics of RubyInline gem are a bit tricky – Moving beyond defining individual methods becomes much more complicated – Best documentation for this happens to 'inline.rb' in the RubyInline source code
  • 12. Native extensions • Address some of the limitations of FFI and inline C++ code techniques • Compiled prior to runtime, but they are generally subject to rigorous runtime requirements • Typically implemented using the Ruby C API • Our simple example requires two files: – simon_native.c, which contains the implementation code – extconf.rb, to generate a Makefile • simon_native.c must include Init_simon_native(), which is called by the Ruby VM to load the extension
  • 13. Native extensions #include <ruby.h> #include <stdio.h> VALUE says(VALUE _self, VALUE str) { Check_Type(str, T_STRING); puts(StringValueCStr(str)); return Qnil; } voidInit_simon_native() { VALUE mod=rb_define_module("Simon"); const intnum_args =1; rb_define_module_function(mod, "says", says, num_args); } simon_native.c
  • 14. Native extensions require 'mkmf' #Generates aMakefile tocompile simon_native.c intoa bundle #that can be loaded intoa Ruby VM create_makefile 'simon_native' extconf.rb Running 'make' should generate a bundle that can be loaded into your Ruby program like so: require './simon_native' Simon.says 'Hello' Hello
  • 15. Native extensions Limitations • Requires code to be written in C – Assumptions around considerations such as file extensions • Uses Ruby C API, which is not terribly user friendly • What about C++?
  • 16. Native extensions with C++ Using the 'rice' gem • Rice is a C++ wrapper for Ruby's C API • Provides classes and templates that make the Ruby API easier and safer to use • Also provides template functions that can take an existing C++ class and make it available to Ruby code • Minor changes to extconf.rb are required
  • 17. Native extensions with C++ simon_native_rice.cpp #include <iostream> #include "rice/Module.hpp" using namespace Rice; void says(const char *str) { std::cout <<str << std::endl; } extern "C" voidInit_simon_native_rice() { define_module("Simon") .define_module_function("says", &says); }
  • 18. Native extensions with C++ extconf.rb require 'mkmf-rice' #Assumes the presence ofa file named 'simon_native_rice.cpp' create_makefile 'simon_native_rice'
  • 19. Native extensions with C++ Wrapping C++ classes • Say we have an existing C++ class that we want to make accessible via Ruby • Declared in simon.hpp: #pragmaonce #include <iostream> class Simon { void says(const char * str) { std::cout <<str << std::endl; } }
  • 20. Wrapping C++ classes simon_native_rice_wrapper.cpp #include "rice/Constructor.hpp" #include "rice/Data_Type.hpp" #include "simon.hpp" using namespace Rice; extern "C" voidInit_simon_native_rice_wrapper() { Data_Type<Simon> rb_cSimon = define_class<Simon>("Simon") .define_constructor(Constructor<Simon>()) .define_method("says", &Simon::says); }
  • 21. Native extensions with C++ extconf.rb require 'mkmf-rice' #instead of'mkmf' create_makefile 'simon_native_rice_wrapper' require './simon_native_rice_wrapper' simon =Simon.new simon.says 'Hello' After running 'make', usage is similar to the example for the 'RubyInline' gem:
  • 22. Resources • Core documentation: https://ruby-doc.org/core- 2.3.3/doc/extension_rdoc.html (Beware the version number in this link) • Aaron Bedra's Extending Ruby guide http://aaronbedra.com/extending-ruby • Pat Shaughnessy’s book: Ruby Under a Microscope
  • 23. Resources • IBM's Building Ruby extensions in C++ using Rice https://www.ibm.com/developerworks/library/os- extendruby/index.html • Chris Lalancette's in-depth series on writing Ruby extensions in C, which covers numerous topics: http://clalance.blogspot.com/2011/01/writing-ruby- extensions-in-c-part-1.html