SlideShare ist ein Scribd-Unternehmen logo
Writing a Gem
with native extensions
Tristan Penman
Melbourne Ruby Meetup, August 2018
A whirlwind tour
 What are they?
 Native extensions allow you to extend the functionality
available in Ruby by writing code in natively compiled
languages such as C, C++, or even Rust.
 This talk shows how native extensions can be used to
interact with a third-party library written in C.
 The final code from this talk can be found on Github:
 https://github.com/tristanpenman/simple-clipboard
Native extensions
A brief introduction
Native extensions
Examples
• 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.
libclipboard
 libclipboard is a cross-platform clipboard library
 Simple C-based API:
 clipboard_new - create a context through which to access
the user's clipboard
 clipboard_free - free any memory allocated by
clipboard_new
 clipboard_text - read the contents of the clipboard as text
 clipboard_set_text - replace the contents of the clipboard
with new text
libclipboard
git clone https://github.com/jtanx/libclipboard
cd libclipboard
mkdir build
cd build
cmake ..
make -j4
sudo make install
 Must be built from source
 Requires git, cmake, and a C++ compiler tool-chain:
simple_clipboard
 We will use a native extension to wrap libclipboard with a
Module that we can use in Ruby code:
module SimpleClipboard
def get_text
#TODO: Return current contents ofclipboard,ornil
raise NotImplementedError
end
def set_text(new_text)
#TODO: Update clipboard; return previous contents, ornil
raise NotImplementedError
end
end
Extending Ruby using C
 To create our native extension we need two files:
 extconf.rb
 simple_clipboard.c
Extending Ruby using C
require 'mkmf'
$LOCAL_LIBS << '-lclipboard'
if RUBY_PLATFORM =~ /darwin/
$LDFLAGS <<' -framework AppKit'
end
create_header
create_makefile 'simple_clipboard/simple_clipboard'
extconf.rb
Extending Ruby using C
simple_clipboard.c (1/2)
#include <ruby.h>
#include <libclipboard.h>
VALUEget_text(VALUE _self) {
VALUE result = Qnil;
char *text = clipboard_text(cb);
if (text) {
result =rb_str_new(text, strlen(text));
free(text);
}
return result;
}
// continued on next slide...
Extending Ruby using C
simple_clipboard.c (2/2)
// continued from previous slide
VALUEset_text(VALUE _self, VALUE str) {
// omitted, since it is similar to get_text
}
voidInit_simple_clipboard() {
VALUE m =rb_define_module("SimpleClipboard");
rb_define_module_function(m, "get_text", get_text, 0);
rb_define_module_function(m, "set_text", set_text, 1);
}
 Run 'ruby extconf.rb' to generate:
 Header file (extconf.h, which is redundant in this case)
 Makefile
 (also mkmf.log)
 Run ’make’ to compile the extension
 On Mac OS X, creates a .bundle file
 On Linux, creates a .so
 On Windows, creates a .dll
Extending Ruby using C
2.3.3:001> require './simple_clipboard'
=>true
2.3.3:002> SimpleClipboard.get_text
=>"Extending Ruby using C"
2.3.3:003> SimpleClipboard.set_text "Hello world"
=>"Extending Ruby using C"
2.3.3:004> SimpleClipboard.get_text
=>"Hello world"
Extending Ruby using C
IRB session
Extending Ruby using C
In a nutshell
 For an extension named 'xyz' we need:
 An extconf.rb file and source file called 'xyz.c'
 In the 'xyz.c' file, a function called Init_xyz
 A native extension is free to:
 define modules, classes and methods that operate on
Ruby values, via an opaque C datatype 'VALUE'
 Call existing Ruby code
 Crash the current process
 And more generally, call 'undefined behavior'
How to include C code in a gem
 Okay, safety be damned, we want performance…
or legacy functionality…
or something.
 lib/
 simple_clipboard/
 version.rb
 simple_clipboard.rb
 simple_clipboard.gemspec
How to include C code in a gem
Layout without a native extension
How to include C code in a gem
Layout with a native extension
 ext/
 simple_clipboard/
 extconf.rb
 simple_clipboard.c
 lib/
 simple_clipboard/
 version.rb
 simple_clipboard.rb
 simple_clipboard.gemspec
#Boilerplate omitted
Gem::Specification.new do |s|
s.name ='simple_clipboard'
s.version =SimpleClipboard::VERSION
s.date ='2018-07-24'
s.summary ='Simple clipboardexample gem'
s.authors =['TristanPenman']
s.email ='tristan@tristanpenman.com'
s.licenses =['MIT']
#continued on next slide...
How to include C code in a gem
simple_clipboard.gemspec (1/2)
#continued from previous slide...
s.extensions =['ext/simple_clipboard/extconf.rb']
#Tell bundler where to findthe code forour gem
s.require_paths =['lib']
#Files toinclude in bundle
s.files =['ext/simple_clipboard/simple_clipboard.c',
'lib/simple_clipboard.rb',
'lib/simple_clipboard/version.rb']
end
How to include C code in a gem
simple_clipboard.gemspec (2/2)
How to include C code in a gem
 Run 'gem build simple_clipboard.gemspec':
 Does not actually compile native extension
 Creates 'simple_clipboard-0.0.1.gem'
 Run 'gem install simple_clipboard-0.0.1.gem'
 This is when bundler will build the native extension
 And this why, when things go wrong while building gems
such as nokigiri, that you can get very complex error
messages
$ gem install simple_clipboard-0.0.1.gem
How to include C code in a gem
Example
Building native extensions. This could take a while...
Successfully installed simple_clipboard-0.0.1
Parsing documentation forsimple_clipboard-0.0.1
Done installing documentation for simple_clipboard after 0 seconds
1 gem installed
2.3.3 :001 >require 'simple_clipboard'
=> true
2.3.3 :002 > SimpleClipboard.get_text
=> "Extending Ruby using C"
2.3.3 :003 > SimpleClipboard.set_text "Hello world"
=> "Extending Ruby using C"
2.3.3 :004 > SimpleClipboard.get_text
=> "Hello world"
Extending Ruby using C
IRB session
Testing native extensions
require "bundler/gem_tasks"
require "rspec/core/rake_task"
require 'rake/extensiontask'
desc "simple_clipboard unit tests"
RSpec::Core::RakeTask.new(:spec) do|t|
t.pattern ="spec/*_spec.rb"
t.verbose =true
End
#continued on next slide...
Rakefile (1/2)
Testing native extensions
#continued fromprevious slide
Rake::ExtensionTask.new do|ext|
ext.name ='simple_clipboard'
ext.source_pattern ="*.{c,h}"
ext.ext_dir ='ext/simple_clipboard'
ext.lib_dir ='lib/simple_clipboard'
ext.gem_spec =
Gem::Specification.load('simple_clipboard.gemspec')
end
#Default is tocompile native extension then runtests
task :default =>[:compile, :spec]
Rakefile (2/2)
Testing native extensions
1. Run 'rake' to compile and run tests
2. Run 'rake compile' to only compile native extension
 Compiles the native extension, then copies
simple_clipboard.[bundle|so|dll] file into 'lib/simple_clipboard'
3. Run 'rake spec' to only run tests
 Assumes that native extension (e.g. simple_clipboard.bundle) has
already been copied to 'lib/simple_clipboard' directory
Rake tasks
Resources
• Useful reference implementation of a
Gem with a native extension:
https://github.com/neilslater/ruby_nex_c
• Core documentation:
https://ruby-doc.org/core-
2.3.3/doc/extension_rdoc.html
(Beware the version number in this link)
• Pat Shaughnessy’s book:
Ruby Under a Microscope
Resources
• RubyGems documentation
https://guides.rubygems.org/gems-with-extensions/
• Aaron Bedra's Extending Ruby guide
http://aaronbedra.com/extending-ruby
• 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
(12 parts in total)
Thanks for listening

Weitere ähnliche Inhalte

Was ist angesagt?

Day CRX Introduction
Day CRX IntroductionDay CRX Introduction
Day CRX Introduction
Cédric Hüsler
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mruby
Hiroshi SHIBATA
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
Hiroshi SHIBATA
 
Hijacking Ruby Syntax in Ruby
Hijacking Ruby Syntax in RubyHijacking Ruby Syntax in Ruby
Hijacking Ruby Syntax in Ruby
SATOSHI TAGOMORI
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rb
Hiroshi SHIBATA
 
Practical ngx_mruby
Practical ngx_mrubyPractical ngx_mruby
Practical ngx_mruby
Hiroshi SHIBATA
 
Experiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRubyExperiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRuby
Matthew Gaudet
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mruby
Hiroshi SHIBATA
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?
Dinh Pham
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
Hiroshi SHIBATA
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
Hiroshi SHIBATA
 
Leave end-to-end testing to Capybara
Leave end-to-end testing to CapybaraLeave end-to-end testing to Capybara
Leave end-to-end testing to Capybara
Hiroshi SHIBATA
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
Hiroshi SHIBATA
 
Web Development in Perl
Web Development in PerlWeb Development in Perl
Web Development in Perl
Naveen Gupta
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015
Charles Nutter
 
mruby で mackerel のプラグインを作るはなし
mruby で mackerel のプラグインを作るはなしmruby で mackerel のプラグインを作るはなし
mruby で mackerel のプラグインを作るはなし
Hiroshi SHIBATA
 
Nodejs Event Driven Concurrency for Web Applications
Nodejs Event Driven Concurrency for Web ApplicationsNodejs Event Driven Concurrency for Web Applications
Nodejs Event Driven Concurrency for Web Applications
Ganesh Iyer
 
Gate of Agile Web Development
Gate of Agile Web DevelopmentGate of Agile Web Development
Gate of Agile Web Development
Koichi ITO
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
Hiroshi SHIBATA
 
Apache thrift-RPC service cross languages
Apache thrift-RPC service cross languagesApache thrift-RPC service cross languages
Apache thrift-RPC service cross languages
Jimmy Lai
 

Was ist angesagt? (20)

Day CRX Introduction
Day CRX IntroductionDay CRX Introduction
Day CRX Introduction
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mruby
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
 
Hijacking Ruby Syntax in Ruby
Hijacking Ruby Syntax in RubyHijacking Ruby Syntax in Ruby
Hijacking Ruby Syntax in Ruby
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rb
 
Practical ngx_mruby
Practical ngx_mrubyPractical ngx_mruby
Practical ngx_mruby
 
Experiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRubyExperiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRuby
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mruby
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 
Leave end-to-end testing to Capybara
Leave end-to-end testing to CapybaraLeave end-to-end testing to Capybara
Leave end-to-end testing to Capybara
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
 
Web Development in Perl
Web Development in PerlWeb Development in Perl
Web Development in Perl
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015
 
mruby で mackerel のプラグインを作るはなし
mruby で mackerel のプラグインを作るはなしmruby で mackerel のプラグインを作るはなし
mruby で mackerel のプラグインを作るはなし
 
Nodejs Event Driven Concurrency for Web Applications
Nodejs Event Driven Concurrency for Web ApplicationsNodejs Event Driven Concurrency for Web Applications
Nodejs Event Driven Concurrency for Web Applications
 
Gate of Agile Web Development
Gate of Agile Web DevelopmentGate of Agile Web Development
Gate of Agile Web Development
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
Apache thrift-RPC service cross languages
Apache thrift-RPC service cross languagesApache thrift-RPC service cross languages
Apache thrift-RPC service cross languages
 

Ähnlich wie Writing a Gem with native extensions

Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
rivierarb
 
introduction-infra-as-a-code using terraform
introduction-infra-as-a-code using terraformintroduction-infra-as-a-code using terraform
introduction-infra-as-a-code using terraform
niyof97
 
Mac ruby deployment
Mac ruby deploymentMac ruby deployment
Mac ruby deployment
Thilo Utke
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
miguel dominguez
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
MortazaJohari
 
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,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Yevgeniy Brikman
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containers
inside-BigData.com
 
K8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals TrainingK8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals Training
Piotr Perzyna
 
A New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDKA New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDK
Shu-Jeng Hsieh
 
Kubered -Recipes for C2 Operations on Kubernetes
Kubered -Recipes for C2 Operations on KubernetesKubered -Recipes for C2 Operations on Kubernetes
Kubered -Recipes for C2 Operations on Kubernetes
Jeffrey Holden
 
Ruby Meets Cocoa
Ruby Meets CocoaRuby Meets Cocoa
Ruby Meets Cocoa
Robbert
 
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
corehard_by
 
Devry gsp 215 week 7 i lab networking and a tiny web server new
Devry gsp 215 week 7 i lab networking and a tiny web server newDevry gsp 215 week 7 i lab networking and a tiny web server new
Devry gsp 215 week 7 i lab networking and a tiny web server new
williamethan912
 
Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014
biicode
 
Build optimization mechanisms in GitLab and Docker
Build optimization mechanisms in GitLab and DockerBuild optimization mechanisms in GitLab and Docker
Build optimization mechanisms in GitLab and Docker
Dmytro Patkovskyi
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
Arto Artnik
 
stackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Three
stackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Threestackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Three
stackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Three
NETWAYS
 
5 Things I Wish I Knew About Gitlab CI
5 Things I Wish I Knew About Gitlab CI5 Things I Wish I Knew About Gitlab CI
5 Things I Wish I Knew About Gitlab CI
Sebastian Witowski
 
A Check of the Open-Source Project WinSCP Developed in Embarcadero C++ Builder
A Check of the Open-Source Project WinSCP Developed in Embarcadero C++ BuilderA Check of the Open-Source Project WinSCP Developed in Embarcadero C++ Builder
A Check of the Open-Source Project WinSCP Developed in Embarcadero C++ Builder
Andrey Karpov
 
ABCs of docker
ABCs of dockerABCs of docker
ABCs of docker
Sabyrzhan Tynybayev
 

Ähnlich wie Writing a Gem with native extensions (20)

Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
 
introduction-infra-as-a-code using terraform
introduction-infra-as-a-code using terraformintroduction-infra-as-a-code using terraform
introduction-infra-as-a-code using terraform
 
Mac ruby deployment
Mac ruby deploymentMac ruby deployment
Mac ruby deployment
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
 
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,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containers
 
K8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals TrainingK8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals Training
 
A New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDKA New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDK
 
Kubered -Recipes for C2 Operations on Kubernetes
Kubered -Recipes for C2 Operations on KubernetesKubered -Recipes for C2 Operations on Kubernetes
Kubered -Recipes for C2 Operations on Kubernetes
 
Ruby Meets Cocoa
Ruby Meets CocoaRuby Meets Cocoa
Ruby Meets Cocoa
 
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
 
Devry gsp 215 week 7 i lab networking and a tiny web server new
Devry gsp 215 week 7 i lab networking and a tiny web server newDevry gsp 215 week 7 i lab networking and a tiny web server new
Devry gsp 215 week 7 i lab networking and a tiny web server new
 
Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014
 
Build optimization mechanisms in GitLab and Docker
Build optimization mechanisms in GitLab and DockerBuild optimization mechanisms in GitLab and Docker
Build optimization mechanisms in GitLab and Docker
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
stackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Three
stackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Threestackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Three
stackconf 2022: Cluster Management: Heterogeneous, Lightweight, Safe. Pick Three
 
5 Things I Wish I Knew About Gitlab CI
5 Things I Wish I Knew About Gitlab CI5 Things I Wish I Knew About Gitlab CI
5 Things I Wish I Knew About Gitlab CI
 
A Check of the Open-Source Project WinSCP Developed in Embarcadero C++ Builder
A Check of the Open-Source Project WinSCP Developed in Embarcadero C++ BuilderA Check of the Open-Source Project WinSCP Developed in Embarcadero C++ Builder
A Check of the Open-Source Project WinSCP Developed in Embarcadero C++ Builder
 
ABCs of docker
ABCs of dockerABCs of docker
ABCs of docker
 

Kürzlich hochgeladen

How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Alpen-Adria-Universität
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
Postman
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
ssuserfac0301
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Jeffrey Haguewood
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
Brandon Minnick, MBA
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
tolgahangng
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
Ivanti
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 

Kürzlich hochgeladen (20)

How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 

Writing a Gem with native extensions

  • 1. Writing a Gem with native extensions Tristan Penman Melbourne Ruby Meetup, August 2018 A whirlwind tour
  • 2.  What are they?  Native extensions allow you to extend the functionality available in Ruby by writing code in natively compiled languages such as C, C++, or even Rust.  This talk shows how native extensions can be used to interact with a third-party library written in C.  The final code from this talk can be found on Github:  https://github.com/tristanpenman/simple-clipboard Native extensions A brief introduction
  • 3. Native extensions Examples • 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.
  • 4. libclipboard  libclipboard is a cross-platform clipboard library  Simple C-based API:  clipboard_new - create a context through which to access the user's clipboard  clipboard_free - free any memory allocated by clipboard_new  clipboard_text - read the contents of the clipboard as text  clipboard_set_text - replace the contents of the clipboard with new text
  • 5. libclipboard git clone https://github.com/jtanx/libclipboard cd libclipboard mkdir build cd build cmake .. make -j4 sudo make install  Must be built from source  Requires git, cmake, and a C++ compiler tool-chain:
  • 6. simple_clipboard  We will use a native extension to wrap libclipboard with a Module that we can use in Ruby code: module SimpleClipboard def get_text #TODO: Return current contents ofclipboard,ornil raise NotImplementedError end def set_text(new_text) #TODO: Update clipboard; return previous contents, ornil raise NotImplementedError end end
  • 7. Extending Ruby using C  To create our native extension we need two files:  extconf.rb  simple_clipboard.c
  • 8. Extending Ruby using C require 'mkmf' $LOCAL_LIBS << '-lclipboard' if RUBY_PLATFORM =~ /darwin/ $LDFLAGS <<' -framework AppKit' end create_header create_makefile 'simple_clipboard/simple_clipboard' extconf.rb
  • 9. Extending Ruby using C simple_clipboard.c (1/2) #include <ruby.h> #include <libclipboard.h> VALUEget_text(VALUE _self) { VALUE result = Qnil; char *text = clipboard_text(cb); if (text) { result =rb_str_new(text, strlen(text)); free(text); } return result; } // continued on next slide...
  • 10. Extending Ruby using C simple_clipboard.c (2/2) // continued from previous slide VALUEset_text(VALUE _self, VALUE str) { // omitted, since it is similar to get_text } voidInit_simple_clipboard() { VALUE m =rb_define_module("SimpleClipboard"); rb_define_module_function(m, "get_text", get_text, 0); rb_define_module_function(m, "set_text", set_text, 1); }
  • 11.  Run 'ruby extconf.rb' to generate:  Header file (extconf.h, which is redundant in this case)  Makefile  (also mkmf.log)  Run ’make’ to compile the extension  On Mac OS X, creates a .bundle file  On Linux, creates a .so  On Windows, creates a .dll Extending Ruby using C
  • 12. 2.3.3:001> require './simple_clipboard' =>true 2.3.3:002> SimpleClipboard.get_text =>"Extending Ruby using C" 2.3.3:003> SimpleClipboard.set_text "Hello world" =>"Extending Ruby using C" 2.3.3:004> SimpleClipboard.get_text =>"Hello world" Extending Ruby using C IRB session
  • 13. Extending Ruby using C In a nutshell  For an extension named 'xyz' we need:  An extconf.rb file and source file called 'xyz.c'  In the 'xyz.c' file, a function called Init_xyz  A native extension is free to:  define modules, classes and methods that operate on Ruby values, via an opaque C datatype 'VALUE'  Call existing Ruby code  Crash the current process  And more generally, call 'undefined behavior'
  • 14. How to include C code in a gem  Okay, safety be damned, we want performance… or legacy functionality… or something.
  • 15.  lib/  simple_clipboard/  version.rb  simple_clipboard.rb  simple_clipboard.gemspec How to include C code in a gem Layout without a native extension
  • 16. How to include C code in a gem Layout with a native extension  ext/  simple_clipboard/  extconf.rb  simple_clipboard.c  lib/  simple_clipboard/  version.rb  simple_clipboard.rb  simple_clipboard.gemspec
  • 17. #Boilerplate omitted Gem::Specification.new do |s| s.name ='simple_clipboard' s.version =SimpleClipboard::VERSION s.date ='2018-07-24' s.summary ='Simple clipboardexample gem' s.authors =['TristanPenman'] s.email ='tristan@tristanpenman.com' s.licenses =['MIT'] #continued on next slide... How to include C code in a gem simple_clipboard.gemspec (1/2)
  • 18. #continued from previous slide... s.extensions =['ext/simple_clipboard/extconf.rb'] #Tell bundler where to findthe code forour gem s.require_paths =['lib'] #Files toinclude in bundle s.files =['ext/simple_clipboard/simple_clipboard.c', 'lib/simple_clipboard.rb', 'lib/simple_clipboard/version.rb'] end How to include C code in a gem simple_clipboard.gemspec (2/2)
  • 19. How to include C code in a gem  Run 'gem build simple_clipboard.gemspec':  Does not actually compile native extension  Creates 'simple_clipboard-0.0.1.gem'  Run 'gem install simple_clipboard-0.0.1.gem'  This is when bundler will build the native extension  And this why, when things go wrong while building gems such as nokigiri, that you can get very complex error messages
  • 20. $ gem install simple_clipboard-0.0.1.gem How to include C code in a gem Example Building native extensions. This could take a while... Successfully installed simple_clipboard-0.0.1 Parsing documentation forsimple_clipboard-0.0.1 Done installing documentation for simple_clipboard after 0 seconds 1 gem installed
  • 21. 2.3.3 :001 >require 'simple_clipboard' => true 2.3.3 :002 > SimpleClipboard.get_text => "Extending Ruby using C" 2.3.3 :003 > SimpleClipboard.set_text "Hello world" => "Extending Ruby using C" 2.3.3 :004 > SimpleClipboard.get_text => "Hello world" Extending Ruby using C IRB session
  • 22. Testing native extensions require "bundler/gem_tasks" require "rspec/core/rake_task" require 'rake/extensiontask' desc "simple_clipboard unit tests" RSpec::Core::RakeTask.new(:spec) do|t| t.pattern ="spec/*_spec.rb" t.verbose =true End #continued on next slide... Rakefile (1/2)
  • 23. Testing native extensions #continued fromprevious slide Rake::ExtensionTask.new do|ext| ext.name ='simple_clipboard' ext.source_pattern ="*.{c,h}" ext.ext_dir ='ext/simple_clipboard' ext.lib_dir ='lib/simple_clipboard' ext.gem_spec = Gem::Specification.load('simple_clipboard.gemspec') end #Default is tocompile native extension then runtests task :default =>[:compile, :spec] Rakefile (2/2)
  • 24. Testing native extensions 1. Run 'rake' to compile and run tests 2. Run 'rake compile' to only compile native extension  Compiles the native extension, then copies simple_clipboard.[bundle|so|dll] file into 'lib/simple_clipboard' 3. Run 'rake spec' to only run tests  Assumes that native extension (e.g. simple_clipboard.bundle) has already been copied to 'lib/simple_clipboard' directory Rake tasks
  • 25. Resources • Useful reference implementation of a Gem with a native extension: https://github.com/neilslater/ruby_nex_c • Core documentation: https://ruby-doc.org/core- 2.3.3/doc/extension_rdoc.html (Beware the version number in this link) • Pat Shaughnessy’s book: Ruby Under a Microscope
  • 26. Resources • RubyGems documentation https://guides.rubygems.org/gems-with-extensions/ • Aaron Bedra's Extending Ruby guide http://aaronbedra.com/extending-ruby • 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 (12 parts in total)