3. In order to compile C code make and gcc (or
clang for macOS) should be installed.
At systems with the APT package manager:
$ sudo apt install -y make gcc
4. Native Extension
● C code that’s included inside the Ruby gem
● Calls the external components API
● Converts parameters and return values between the external library format and Ruby
interpreter expectations
● Native Extension C code is directly executed by VM (MRI, YARV, etc)
5. Why do we write C extensions?
● Ruby’s C APIs are bridge between the Ruby and
C world
● High performing C code which is directly
connected to Ruby code (No need to waste the
time for data interchange between different
processes or services)
● Integratoin with C libraries (nokogiri, mysql2)
6. Why we do NOT write C extensions?
● 10x harder to write, maintain, and understand
● More issues to consider, such as memory
management and type safety
● Ruby API is huge and largely undocumented
● Might require delving through the Ruby source code
● Ruby source uses some fairly sophisticated C
8. extconf.rb
MakeMakefile
https://www.rubydoc.info/stdlib/mkmf/Ma
keMakefile - mkmf docs
https://silverhammermba.github.io/embe
rb/extend/ - docs
https://makefiletutorial.com/ - Makefiles
tutorial
https://github.com/dmke/ktoblzcheck/blo
b/master/ext/ktoblzcheck/extconf.rb -
original extconf.rb file
mkmf.rb is used by Ruby C extensions
to generate a Makefile which will
correctly compile and link the C
extension to Ruby and a third-party
library.
10. Ruby C API
● #include <ruby.h> - header with Ruby C API Macros
● void Init_math_demo() - called when compiled extension
file is required: require ‘math_demo/math_demo’
● ID id_puts = rb_intern("puts") - type and method that
converts C string to ruby symbol :puts
● Type VALUE represents Ruby Object within C
● void rb_define_method(VALUE klass, const char *name,
VALUE (*func)(ANYARGS), int argc);
● NUM2DBL(rb_value), DBL2NUM(c_value) - few of many
Ruby to C and C to Ruby conversion macroses
11. Ruby Native C Useful
Links
https://blog.peterzhu.ca/ruby-c-ext/ - A Rubyist's Walk Along the C-side
http://silverhammermba.github.io/emberb/c/ - The Ruby C API
https://github.com/andremedeiros/ruby-c-cheat-sheet - Ruby C Cheat Sheet
https://github.com/ruby/ruby/blob/master/doc/extension.rdoc - Official documentation
https://github.com/miyucy/sophia-ruby/blob/master/ext/sophia.c - Good practical usage example
https://dev.to/vinistock/creating-ruby-native-extensions-kg1 - Creating Ruby native extensions
http://aaronbedra.com/extending-ruby/ - libxml example
http://clalance.blogspot.com/2011/01/writing-ruby-extensions-in-c-part-1.html - In-depth series on Ruby
extensions in C
https://ruby-doc.com/docs/ProgrammingRuby/html/ext_ruby.html - Extending Ruby
12. ● https://github.com/seattlerb/rubyinline - gem
● Allows to write foreign code within ruby code
● Automatically determines if the code has
changed and builds it only when necessary
● Extensions are then automatically loaded into
the class/module that defines it
● Code is being compiled on the fly, so first run
might be slow, then it is cached for next call
● Not supporting alternative names for data
types at called function signature (Ignores
their definitions in the headers, maybe
requires some unknown magic to fix it)
Ruby Inline
13. Foreign Function Interface
(Ruby-FFI gem)
● Loading dynamically-linked native
libraries programmatically
● Binding functions within libraries
● Calling these functions from Ruby
code
● Works without changes on CRuby
(MRI), JRuby, Rubinius and
TruffleRuby
Requirements
C compiler (Xcode, gcc, clang)
libffi library and dev headers (libffi-
dev or libffi-devel packages)
https://github.com/ffi/ffi/wiki/why-use-ffi
Features
● Intuitive DSL
● Supports all C native types
● C structs (also nested), enums and global variables
● Callbacks from C to Ruby
● Automatic garbage collection of native memory
14. FFI Basic Usage
attach_function
● First argument* gives the name we want to use when calling the method, - so snake-case 🐍
instead of camel-case 🐫
● Second argument is the actual name of the function in the C library so FFI can find it
● Third argument is an array of types which informs FFI of the argument types we expect to be
passing in (in order)
● The last argument is the expected type of the return value
ffi_lib
● loads ‘libh3’ library
● accepts names of or paths
to libraries to load
15. FFI Useful Links
● https://github.com/ffi/ffi gem docs and wiki https://github.com/ffi/ffi/wiki
● https://www.rubydoc.info/github/ffi/ffi - ruby doc
● https://www.rubyguides.com/2019/05/ruby-ffi/ - Play Media Files with VLC and FFI
● https://stuart.com/blog/tech/ruby-bindings-extensions/ - FFI examle with Uber H3 library
https://github.com/StuartApp/h3_ruby - ruby gem that connects with H3 library via FFI
● https://github.com/hybridgroup/rubyserial/blob/master/lib/rubyserial/linux_constants.rb - usage
example with method attachment and C structs
● https://www.varvet.com/blog/advanced-topics-in-ruby-ffi/ - Advanced Topics
● https://spin.atomicobject.com/2013/02/15/ffi-foreign-function-interfaces/ - Foreign Function
Interfaces for Fun & Industry
16. Fiddle
● Added to Ruby's standard library in 1.9.x
● Fiddle is an extension to translate a foreign
function interface (FFI) with ruby.
● Wraps libffi, a popular C library which provides
a portable interface that allows code written in
one language to call code written in another
language
● Allows to inspect and alter the ruby
interpreter as it runs
17. Fiddle Usage
Fiddle::Importer - A DSL that provides the means to dynamically
load libraries and build modules around them including calling extern
functions within the C library that has been loaded. https://ruby-
doc.org/stdlib-2.5.3/libdoc/fiddle/rdoc/Fiddle/Importer.html
18. Fiddle Useful Links
● https://www.honeybadger.io/blog/use-any-c-library-from-ruby-via-fiddle-the-ruby-standard-
librarys-best-kept-secret/ - Use any C library from Ruby via Fiddle
● https://medium.com/@astantona/fiddling-with-rubys-fiddle-39f991dd0565 - Fiddling with
Ruby’s Fiddle
● https://stackoverflow.com/questions/50785133/ruby-fiddle-define-struct - Ruby Fiddle
Structs
● https://ruby-doc.org/stdlib-3.0.2/libdoc/fiddle/rdoc/Fiddle.html rDoc
● https://github.com/ruby/fiddle Gem
19. Performance Benchmarks
For Levenshtein distance algorithm
Approach Iterations Per Second Elapsed time Memory Allocations
Native C Extension
(Ruby C APi)
1544254.8 i/s 0.000009 40 allocated
Ruby Inline 1342312.5 i/s - 1.15x
(± 0.00) slower
0.000011 80 allocated - 2.00x
more
FFI 1291394.3 i/s - 1.20x
(± 0.00) slower
0.000013 40 (same as Native C)
Fiddle 269478.0 i/s - 5.73x (±
0.00) slower
0.000025 317 allocated - 7.92x
more
Ruby, RubyGems algorithm 111615.4 i/s - 13.84x
(± 0.00) slower
0.000126 528 allocated - 13.20x
more
20. Usability Comparison
Approach Pros Cons
Native C
Extension
(Ruby C APi)
Huge Performance as it is the most close
to Native C as Ruby can get to
Usage complexity, low level coding (memory
management, type safety), boilerplate code,
not fully documented
Ruby Inline Simplest usage for Native C.
Just copy-paste the C code into Ruby
and run it inline. No need to compile
code separately.
1.15x times slower and 2x times allocates more
memory than native C
Compilation at runtime
Not working with dynamically linked libraries
FFI Easy to use, automatic garbage
collection, customizable, good level of
control, good documentation.
1.2x times slower than native C
Not ruby stdlib gem as Fiddle
Fiddle Simplest FFI, almost verbatim mapping
of the C code to Ruby. Ruby stdlib gem.
4.5x times slower and 7.92x times allocates
more memory than FFI
Ruby Easy and comfortable for Rubyists. The
most programmer friendly solution
13.84x times slower and 13.20x more memory
usage as it can not compete with Native C
21. I need C code in Ruby
(For Performance or External C Library Integration)
Yes No
Super Fast!
Memory Efficient!
Do not care about complexity!
Fast and Easy
Native Ruby C API FFI
Which one
to choose?
Easier / No Dependencies
(Ruby Stdlib) / Slower
Fiddle
Few lines of C Code
Ruby Inline
Do you really need C for
so few lines of code?
Yes No
Faster and
Memory Efficient
Ruby
22. ● https://www.learn-c.org/ Learn C
● https://www.tutorialspoint.com/cprogramming/index.htm C Tutorial
● https://github.com/oz123/awesome-c Some C Libraries to practice Ruby integration
● https://vtd-xml.sourceforge.io/ Good C Library to practice Ruby Integration,
Especially this https://vtd-xml.sourceforge.io/codeSample/cs4.html example
● https://riptutorial.com/ruby/example/17682/working-with-c-structs Working with C
Structs via Ruby Native C API
More of the Useful Links! :)