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

PPT
Basics of Machine Learning
PDF
"An Introduction to Machine Learning and How to Teach Machines to See," a Pre...
PDF
Object oriented concepts ppt
PPT
PPT
Computer graphics
PPTX
The Internet of Things – Shaping the Future
PPTX
CYBER TERRORISM
PPTX
Introduction to Machine Learning
Basics of Machine Learning
"An Introduction to Machine Learning and How to Teach Machines to See," a Pre...
Object oriented concepts ppt
Computer graphics
The Internet of Things – Shaping the Future
CYBER TERRORISM
Introduction to Machine Learning

What's hot (20)

PPTX
Transfer learning-presentation
DOC
Cybersecurity
PPTX
Back propagation network
PPTX
Cyber security ppt
PDF
Machine Learning: Applications, Process and Techniques
PPTX
Face Detection Using MATLAB (SUD)
PDF
K - Nearest neighbor ( KNN )
PPTX
Computer graphics
PDF
The Anatomy of a Data Breach
PPTX
Face Recognition using OpenCV
PPT
Machine Learning
PDF
Computer architecture lesson 1
PDF
PPTX
CYBER SECURITY
PPSX
PPTX
Network security (vulnerabilities, threats, and attacks)
PPTX
Introduction to machine learning
PDF
Digital image processing
PPTX
Cloud Computing- components, working, pros and cons
PDF
Machine Learning Course | Edureka
Transfer learning-presentation
Cybersecurity
Back propagation network
Cyber security ppt
Machine Learning: Applications, Process and Techniques
Face Detection Using MATLAB (SUD)
K - Nearest neighbor ( KNN )
Computer graphics
The Anatomy of a Data Breach
Face Recognition using OpenCV
Machine Learning
Computer architecture lesson 1
CYBER SECURITY
Network security (vulnerabilities, threats, and attacks)
Introduction to machine learning
Digital image processing
Cloud Computing- components, working, pros and cons
Machine Learning Course | Edureka
Ad

Similar to Extending Ruby using C++ (20)

PPTX
Writing a Gem with native extensions
ODP
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
PPTX
Introduction to Ruby Native Extensions and Foreign Function Interface
PDF
ruby-cocoa
PDF
ruby-cocoa
PDF
Mac ruby deployment
PPT
C#.NET
PPT
CPlusPus
PPT
Abhishek lingineni
PPT
C++_programs.ppt
PPT
C++_programs.ppt
PPT
C++ programming: Basic introduction to C++.ppt
PPT
C++_programs.ppt
PPT
C++_programs.ppt
PPT
C++_programs.ppt
PPT
C++_programs.ppt
PDF
Ruby Meets Cocoa
PDF
Everything-as-code - A polyglot adventure
PDF
Everything-as-code. A polyglot adventure. #DevoxxPL
PPTX
Binding Objective-C Libraries, Miguel de Icaza
Writing a Gem with native extensions
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Introduction to Ruby Native Extensions and Foreign Function Interface
ruby-cocoa
ruby-cocoa
Mac ruby deployment
C#.NET
CPlusPus
Abhishek lingineni
C++_programs.ppt
C++_programs.ppt
C++ programming: Basic introduction to C++.ppt
C++_programs.ppt
C++_programs.ppt
C++_programs.ppt
C++_programs.ppt
Ruby Meets Cocoa
Everything-as-code - A polyglot adventure
Everything-as-code. A polyglot adventure. #DevoxxPL
Binding Objective-C Libraries, Miguel de Icaza
Ad

Recently uploaded (20)

PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
history of c programming in notes for students .pptx
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
medical staffing services at VALiNTRY
PDF
System and Network Administraation Chapter 3
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
How Creative Agencies Leverage Project Management Software.pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Upgrade and Innovation Strategies for SAP ERP Customers
CHAPTER 2 - PM Management and IT Context
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
history of c programming in notes for students .pptx
Understanding Forklifts - TECH EHS Solution
Wondershare Filmora 15 Crack With Activation Key [2025
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
How to Migrate SBCGlobal Email to Yahoo Easily
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Which alternative to Crystal Reports is best for small or large businesses.pdf
medical staffing services at VALiNTRY
System and Network Administraation Chapter 3
PTS Company Brochure 2025 (1).pdf.......
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Softaken Excel to vCard Converter Software.pdf
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises

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