Slide 1

Slide 1 text

Developing Ruby gems with native extensions by @crackofdusk 1 / 16

Slide 2

Slide 2 text

Why use native extensions? 2 / 16

Slide 3

Slide 3 text

Bindings to existing native libraries 3 / 16

Slide 4

Slide 4 text

Speed up hot code paths 4 / 16

Slide 5

Slide 5 text

Why not use native extensions 5 / 16

Slide 6

Slide 6 text

The current speed is acceptable 6 / 16

Slide 7

Slide 7 text

The speed can be improved by an algorithmic change 7 / 16

Slide 8

Slide 8 text

You are uncomfortable with C and there is a another communication channel with the underlying system (HTTP, UNIX sockets, ...) 8 / 16

Slide 9

Slide 9 text

Let’s dive in 9 / 16

Slide 10

Slide 10 text

$ tree . ├── ext │ └── hello │ ├── extconf.rb │ └── hello.c └── hello.gemspec ext/hello/extconf.rb require 'mkmf' have_library('hello') create_makefile('hello/hello') ext/hello/hello.c #include void Init_hello() { // ... } hello.gemspec Gem::Specification.new do |spec| # ... spec.extensions << 'ext/hello/extconf.rb' end 10 / 16

Slide 11

Slide 11 text

$ cd ext/hello $ ruby extconf.rb checking for main() in -lhello... no creating Makefile $ make compiling hello.c linking shared-object hello/hello.so $ irb irb(main):001:0> require './hello' => true 11 / 16

Slide 12

Slide 12 text

$ tree . ├── ext │ └── hello │ ├── extconf.rb │ └── hello.c ├── lib └── Rakefile $ rake compile ... $ ls lib/ hello.so $ irb -Ilib irb(main):001:0> require 'hello' => true Rakefile require 'rake/extensiontask' Rake::ExtensionTask.new('hello') With the rake-compiler gem 12 / 16

Slide 13

Slide 13 text

extconf.rb Checks compilation conditions and generates a Makefile. For example: require 'mkmf' HEADER_DIRS = [ # ... ] LIB_DIRS = [ # ... ] unless find_header('foo/foo.h', *HEADER_DIRS) abort "libfoo is missing. Please install libfoo" end unless find_library('foo', 'foo_imported_function', *LIB_DIRS) abort "libfoo is missing. Please install libfoo" end create_makefile('foo/foo') See the MakeMakefile documentation for all available checks. 13 / 16

Slide 14

Slide 14 text

Library initialization and entry point When the interpreter loads the library LIBRARY, it executes the Init_LIBRARY() function. #include #include void Init_foo(void) { VALUE mFoo = rb_define_module("Foo"); rb_define_singleton_method(mFoo, "bar", bar, 1); //... } 14 / 16

Slide 15

Slide 15 text

Ruby Extension API Used by the library to interact with the Ruby interpreter from the C code. It provides functions to: check data types convert between different types define classes, modules, constants, methods invoke Ruby methods raise exceptions handle allocations and deallocations wrap C pointers into Ruby objects etc. The documentation is in the README.EXT file that comes with the CRuby source code. 15 / 16

Slide 16

Slide 16 text

Further reading Official documentation about making extension libraries for Ruby: https://github.com/ruby/ruby/blob/trunk/README.EXT Rubygems guide about gems with extensions: http://guides.rubygems.org/gems-with-extensions/ The rake-compiler gem: https://github.com/rake-compiler/rake-compiler Writing Ruby C extensions: http://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part- 1.html http://tenderlovemaking.com/2010/12/11/writing-ruby-c-extensions-part- 2.html Native extensions with Java: https://blog.jcoglan.com/2012/08/02/your-first-ruby-native-extension-java/ 16 / 16