SlideShare a Scribd company logo
How to write Ruby
extensions with Crystal
@gaar4ica

Anna Shcherbinina
I like Ruby
5 YO, a lot of stuff
So, I like Ruby
But, sometimes,
I need my code to work
faster
def fibonacci(n)
n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)
end
Case of possible bottle
neck
Ruby has C bindings
C is hard to learn and
understand
Static types Allocating 

memory
And tons of other
complications
for Ruby developer
I’m ruby developer,
I don’t want to write my code in C
I’m ruby developer,
I want to write my code in Ruby.
But to be honest…
Node.js
NET
OWL PDF
XML
Redis
C++
Scala
BASIC
C#
I’m ruby developer,
I want to write my code in Ruby
Also, I like Crystal
Crystal has ruby-like
Spoiler about crystal
Guess the language
# define class Dog
class Dog
def initialize(breed, name)
@breed = breed
@name = name
end
def bark
puts 'Ruff! Ruff!'
end
def display
puts "I am of #{@breed} breed and my name is #{@name}"
end
end

# make an object
d = Dog.new('Labrador', 'Benzy')
Crystal compiles to native
code
Spoiler about crystal
So, I like Crystal
No way
No way
?
C
bindings
C bindings
C layer
Link Crystal classes
and methods to Ruby,
so Ruby knows about
them
Translate 

Ruby-types 

to Crystal-types
So, Crystal lang
WUT?
Compile to efficient 

native code
Statically 

type-checked
Ruby-inspired 

syntax
C bindings
Web Frameworks
• amatista
• amethyst
• kemal
• moonshine
Testing
Search CacheDBDDBD
Third-party 

APIs
Libs
Ready for production or not?
Web apps Microservice
• maths calculation
• small but heavy parts of
projects
What for
Not so like ruby
if @a
# here @a can be nil
end
if @a.is_a?(String)
# here @a is not guaranteed to be a String
end
if @a.responds_to?(:abs)
# here @a is not guaranteed to respond to `abs`
end
The below doesn’t work with instance variables,
class variables or global variables.
Variables
Not so like ruby
To work with these, first assign them to a variable:
if a = @a
# here a can't be nil
end
# Second option: use `Object#try` found in the
standard library
@a.try do |a|
# here a can't be nil
end
if (a = @a).is_a?(String)
# here a is guaranteed to be a String
end
Variables
Not so like ruby
Classes and methods
Not so like ruby
Overloading Return types
Visibility Finalize
Macros
Not so like ruby
class Object
macro def instance_vars_names : Array(String)
{{ @type.instance_vars.map &.name.stringify }}
end
end
class Person
def initialize(@name, @age)
end
end
person = Person.new "John", 30
person.instance_vars_names #=> ["name", "age"]
Threads
Not so like ruby
def generate(chan)
i = 2
loop do
chan.send(i)
i += 1
end
end
def filter(in_chan, out_chan, prime)
loop do
i = in_chan.receive
if i % prime != 0
out_chan.send(i)
end
end
end
ch = Channel(Int32).new
spawn generate(ch)
100.times do
prime = ch.receive
puts prime
ch1 =
Channel(Int32).new
spawn filter(ch, ch1,
prime)
ch = ch1
end
Benchmarking
Time (s)
Go Erlang Crystal Scala Ruby C Crystal Ruby C Crystal Ruby
4.084.082.21
27.92
6.025.08
41.73
6.426.091.971.48
Memory (Mb)
Go Erlang Crystal Scala Ruby C Crystal Ruby C Crystal Ruby
162.40
1.400.40
115.50107.60
32.4030.00
1.505.3017.10
2.00
Threadring Binarytree Fast
Threadring Binarytree Fast
Back to case of
possible bottle neck
def fibonacci(n)
n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)
end
Back to
C
bindings
Less work for C
Passing primitive data structures:
• integer
• string
• boolean
• float / decimal
• etc.
No allocation memory for complex data types
Don’t do a lot of work for casting variables passed as attributes
Ruby C API
Entry point
Then every C extension has to implement a function named
Init_xxxxx (xxxxx being your extension’s name).
It is being executed during the “require” of your extension.
void Init_xxxxx() {
// Code executed during "require"
}
Ruby C API
Types
Ruby C API defines a bunch of handful C constants defining
standard Ruby objects:
C Ruby
Qnil nil
Qtrue TRUE
Qfalse FALSE
rb_cObject Object
rb_mKernel Kernel
rb_cString String
Ruby C API
Declaring modules and classes
// Creating classes
// rb_define_class creates a new class named name
// and inheriting from super.
// The return value is a handle to the new class.
VALUE rb_define_class(const char *name, VALUE super);
// Creating modules
// rb_define_module defines a module whose name
// is the string name.
// The return value is a handle to the module.
VALUE rb_define_module(const char *name);
Ruby C API
Declaring methods
// Creating a method
// rb_define_method defines a new instance method in the class
// or moduleklass.
// The method calls func with argc arguments.
// They differ in how they specify the name - rb_define_method
// uses the constant string name
void rb_define_method(VALUE klass, const char *name, VALUE
(*func)(ANYARGS), int argc);
// rb_define_protected_method and rb_define_private_method are
similar to rb_define_method,
// except that they define protected and private methods,
respectively.
void rb_define_protected_method(VALUE klass, const char *name,
VALUE (*func)(ANYARGS), int argc);
void rb_define_private_method(VALUE klass, const char *name,
VALUE (*func)(ANYARGS), int argc);
Ruby C API
Ruby objects → C types
// Convert Numeric to integer.
long rb_num2int(VALUE obj);
// Convert Numeric to unsigned integer.
unsigned long rb_num2uint(VALUE obj);
// Convert Numeric to double.
double rb_num2dbl(VALUE);
// Convert Ruby string to a String.
VALUE rb_str_to_str(VALUE object);
char* rb_string_value_cstr(volatile VALUE* object_variable);
Ruby C API
C types → Ruby objects
// Convert an integer to Fixnum or Bignum.
INT2NUM( int );
// convert an unsigned integer to Fixnum or Bignum.
UINT2NUM( unsigned int );
// Convert a double to Float.
rb_float_new( double );
// Convert a character string to String.
rb_str_new2( char* );
// Convert a character string to ID (for Ruby function names,
etc.).
rb_intern( char* );
// Convert a character string to a ruby Symbol object.
ID2SYM( rb_intern(char*) );
Ruby C API
Simple example
# my_class.rb
class MyClass
def my_method(param1, param2)
end
end
// my_class_ext.c
static VALUE myclass_mymethod(VALUE rb_self, VALUE rb_param1, VALUE
rb_param2)
{
// Code executed when calling my_method on an object of class MyClass
}
void Init_xxxxx()
{
// Define a new class (inheriting Object) in this module
VALUE myclass = rb_define_class("MyClass", rb_cObject);
// Define a method in this class, taking 2 arguments,
// and using the C method "myclass_method" as its body
rb_define_method(myclass, "my_method", myclass_mymethod, 2);
}
Ruby C API
Simple example
# my_class.rb
class MyClass
def my_method(param1, param2)
end
end
// my_class_ext.c
static VALUE myclass_mymethod(VALUE rb_self, VALUE rb_param1, VALUE
rb_param2)
{
// Code executed when calling my_method on an object of class MyClass
}
void Init_xxxxx()
{
// Define a new class (inheriting Object) in this module
VALUE myclass = rb_define_class("MyClass", rb_cObject);
// Define a method in this class, taking 2 arguments,
// and using the C method "myclass_method" as its body
rb_define_method(myclass, "my_method", myclass_mymethod, 2);
}
Ruby C API
Simple example
# my_class.rb
class MyClass
def my_method(param1, param2)
end
end
// my_class_ext.c
static VALUE myclass_mymethod(VALUE rb_self, VALUE rb_param1, VALUE
rb_param2)
{
// Code executed when calling my_method on an object of class MyClass
}
void Init_xxxxx()
{
// Define a new class (inheriting Object) in this module
VALUE myclass = rb_define_class("MyClass", rb_cObject);
// Define a method in this class, taking 2 arguments,
// and using the C method "myclass_method" as its body
rb_define_method(myclass, "my_method", myclass_mymethod, 2);
}
def fibonacci(n)
n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)
end
Back to case of possible 

bottle neck
And solution
C
A lib declaration groups C functions and types that belong to 

a library.
Crystal extension
It’s easy
lib CrRuby
type VALUE = Void*
$rb_cObject : VALUE
end
Every ruby object is treated as type VALUE in C.
Crystal extension
It’s easy
lib CrRuby
type VALUE = Void*
$rb_cObject : VALUE
end
rb_cObject is a C constant defining standard Ruby Object class.
Crystal extension
It’s easy
lib CrRuby
type VALUE = Void*
$rb_cObject : VALUE
end
lib CrRuby
type VALUE = Void*
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
end
A fun declaration inside a lib binds to a C function.
We bind rb_num2int & rb_int2inum, to use it later.
Crystal extension
It’s easy
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func:
METHOD_FUNC, argc: Int32)
end
Crystal extension
It’s easy
We bind rb_define_class & rb_define_method.
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
Our new and shiny fibonacci method in Crystal.
def fibonacci(n)
n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)
end
Do you see the difference with implementation in Ruby?
Crystal extension
It’s easy
Crystal extension
It’s easy
Let’s create a wrapper for this method, used for:
• convert inbound Ruby-type parameter to Crystal;
• convert outbound result back to Ruby type.
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
Crystal extension
It’s easy
Now we are done with our functions and C bindings.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
Crystal extension
It’s easy
Now we are done with our functions and C bindings.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
Crystal extension
It’s easy
Now we are done with our functions and C bindings.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
Crystal extension
It’s easy
Now we are done with our functions and C bindings.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
Crystal extension
It’s easy
We bind init function, the first one to be called.
As you remember, a function named Init_xxxxx is being executed
during the “require” of your extension.
fun init = Init_cr_math
end
Crystal extension
It’s easy
Firstly, we start garbage collector.
We need to invoke Crystal's "main" function, the one that initializes all
constants and runs the top-level code.
We pass 0 and null to argc and argv.
fun init = Init_cr_math
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
end
Crystal extension
It’s easy
We define class CrMath.
fun init = Init_cr_math
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject)
CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1)
end
Crystal extension
It’s easy
We define class CrMath.
Attach method fibonacci to class.
fun init = Init_cr_math
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject)
CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1)
end
Crystal extension
Ready to compile
We have Crystal library with C bindings.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
fun init = Init_cr_math
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject)
CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1)
end
Crystal extension
Ready to compile
We have method fibonacci_cr and wrapper for it.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
fun init = Init_cr_math
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject)
CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1)
end
Crystal extension
Ready to compile
We have entry point.
lib CrRuby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE
$rb_cObject : VALUE
fun rb_num2int(value : VALUE) : Int32
fun rb_int2inum(value : Int32) : VALUE
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE)
int_value = CrRuby.rb_num2int(value)
CrRuby.rb_int2inum(fibonacci_cr(int_value))
end
def fibonacci_cr(n)
n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2)
end
fun init = Init_cr_math
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject)
CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1)
end
Crystal extension
Ready to compile
Makefile
CRYSTAL = crystal
UNAME = "$(shell uname -ms)"
LIBRARY_PATH = $(shell brew --prefix crystal-lang)/embedded/lib
TARGET = cr_math.bundle
$(TARGET): cr_math.o
$(CC) -bundle -L$(LIBRARY_PATH) -o $@ $^
cr_math.o: cr_math.cr
$(CRYSTAL) build --cross-compile $(UNAME) $<
$ irb
2.1.6 :001 > require './cr_math'
=> true
2.1.6 :002 > CrMath.new.fibonacci(20)
=> 6765
Crystal extension
Using in Ruby
# benchmark.rb
require 'benchmark'
require './cr_math' # We have compiled cr_math.bundle
require './rb_math'
iterations = 10_000
number = 20
Benchmark.bm do |bm|
bm.report("rb") do
iterations.times { RbMath.new.fibonacci(number) }
end
bm.report("cr") do
iterations.times { CrMath.new.fibonacci(number) }
end
end
# rb_math.rb
class RbMath
def fibonacci(n)
return n if n <= 1
fibonacci(n - 1) +
fibonacci(n - 2)
end
end
Crystal extension
Benchmarking
# benchmark.rb
require 'benchmark'
require './cr_math' # We have compiled cr_math.bundle
require './rb_math'
iterations = 10_000
number = 20
Benchmark.bm do |bm|
bm.report("rb") do
iterations.times { RbMath.new.fibonacci(number) }
end
bm.report("cr") do
iterations.times { CrMath.new.fibonacci(number) }
end
end
# rb_math.rb
class RbMath
def fibonacci(n)
return n if n <= 1
fibonacci(n - 1) +
fibonacci(n - 2)
end
end
Crystal extension
Benchmarking
$ ruby benchmark.rb
user system total real
rb 10.270000 0.030000 10.300000 ( 10.314595)
cr 0.460000 0.000000 0.460000 ( 0.464087)
Crystal extension
Benchmarking
Ta-Da!
Thank you
https://twitter.com/gaar4ica
https://github.com/gaar4ica/ruby_ext_in_crystal_math
http://crystal-lang.org/
https://github.com/manastech/crystal
https://github.com/5t111111/ruby_extension_with_crystal
http://blog.jacius.info/ruby-c-extension-cheat-sheet/

More Related Content

What's hot

Square869120 contest #2
Square869120 contest #2Square869120 contest #2
Square869120 contest #2
AtCoder Inc.
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
AtCoder Beginner Contest 006 解説
AtCoder Beginner Contest 006 解説AtCoder Beginner Contest 006 解説
AtCoder Beginner Contest 006 解説
AtCoder Inc.
 
AtCoder Beginner Contest 034 解説
AtCoder Beginner Contest 034 解説AtCoder Beginner Contest 034 解説
AtCoder Beginner Contest 034 解説
AtCoder Inc.
 
AtCoder Regular Contest 017
AtCoder Regular Contest 017AtCoder Regular Contest 017
AtCoder Regular Contest 017
AtCoder Inc.
 
AtCoder Beginner Contest 011 解説
AtCoder Beginner Contest 011 解説AtCoder Beginner Contest 011 解説
AtCoder Beginner Contest 011 解説
AtCoder Inc.
 
AtCoder Regular Contest 043 解説
AtCoder Regular Contest 043 解説AtCoder Regular Contest 043 解説
AtCoder Regular Contest 043 解説
AtCoder Inc.
 
AtCoder Beginner Contest 033 解説
AtCoder Beginner Contest 033 解説AtCoder Beginner Contest 033 解説
AtCoder Beginner Contest 033 解説
AtCoder Inc.
 
AtCoder Beginner Contest 025 解説
AtCoder Beginner Contest 025 解説AtCoder Beginner Contest 025 解説
AtCoder Beginner Contest 025 解説
AtCoder Inc.
 
Arc015途中まで解説
Arc015途中まで解説Arc015途中まで解説
Arc015途中まで解説
AtCoder Inc.
 
AtCoder Beginner Contest 005 解説
AtCoder Beginner Contest 005 解説AtCoder Beginner Contest 005 解説
AtCoder Beginner Contest 005 解説
AtCoder Inc.
 
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムTakuya Akiba
 
AtCoder Regular Contest 036 解説
AtCoder Regular Contest 036 解説AtCoder Regular Contest 036 解説
AtCoder Regular Contest 036 解説
AtCoder Inc.
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~
Yuma Inoue
 
arc047
arc047arc047
arc047
AtCoder Inc.
 
AtCoder Beginner Contest 016 解説
AtCoder Beginner Contest 016 解説AtCoder Beginner Contest 016 解説
AtCoder Beginner Contest 016 解説
AtCoder Inc.
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説
AtCoder Inc.
 
Rolling hash
Rolling hashRolling hash
AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説
AtCoder Inc.
 

What's hot (20)

Square869120 contest #2
Square869120 contest #2Square869120 contest #2
Square869120 contest #2
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
Convex Hull Trick
 
AtCoder Beginner Contest 006 解説
AtCoder Beginner Contest 006 解説AtCoder Beginner Contest 006 解説
AtCoder Beginner Contest 006 解説
 
AtCoder Beginner Contest 034 解説
AtCoder Beginner Contest 034 解説AtCoder Beginner Contest 034 解説
AtCoder Beginner Contest 034 解説
 
AtCoder Regular Contest 017
AtCoder Regular Contest 017AtCoder Regular Contest 017
AtCoder Regular Contest 017
 
AtCoder Beginner Contest 011 解説
AtCoder Beginner Contest 011 解説AtCoder Beginner Contest 011 解説
AtCoder Beginner Contest 011 解説
 
AtCoder Regular Contest 043 解説
AtCoder Regular Contest 043 解説AtCoder Regular Contest 043 解説
AtCoder Regular Contest 043 解説
 
AtCoder Beginner Contest 033 解説
AtCoder Beginner Contest 033 解説AtCoder Beginner Contest 033 解説
AtCoder Beginner Contest 033 解説
 
Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
AtCoder Beginner Contest 025 解説
AtCoder Beginner Contest 025 解説AtCoder Beginner Contest 025 解説
AtCoder Beginner Contest 025 解説
 
Arc015途中まで解説
Arc015途中まで解説Arc015途中まで解説
Arc015途中まで解説
 
AtCoder Beginner Contest 005 解説
AtCoder Beginner Contest 005 解説AtCoder Beginner Contest 005 解説
AtCoder Beginner Contest 005 解説
 
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
 
AtCoder Regular Contest 036 解説
AtCoder Regular Contest 036 解説AtCoder Regular Contest 036 解説
AtCoder Regular Contest 036 解説
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~
 
arc047
arc047arc047
arc047
 
AtCoder Beginner Contest 016 解説
AtCoder Beginner Contest 016 解説AtCoder Beginner Contest 016 解説
AtCoder Beginner Contest 016 解説
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説
 
Rolling hash
Rolling hashRolling hash
Rolling hash
 
AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説
 

Viewers also liked

Rubyの拡張をCrystalで書いてみる
Rubyの拡張をCrystalで書いてみるRubyの拡張をCrystalで書いてみる
Rubyの拡張をCrystalで書いてみる
5t111111
 
Opal - Ruby Style!! Ruby in the browser
Opal - Ruby Style!!  Ruby in the browserOpal - Ruby Style!!  Ruby in the browser
Opal - Ruby Style!! Ruby in the browser
Forrest Chang
 
Global Education and Skills Forum 2017 - Educating Global Citizens
Global Education and Skills Forum  2017 -  Educating Global CitizensGlobal Education and Skills Forum  2017 -  Educating Global Citizens
Global Education and Skills Forum 2017 - Educating Global Citizens
EduSkills OECD
 
Comparative genomics to the rescue: How complete is your plant genome sequence?
Comparative genomics to the rescue: How complete is your plant genome sequence?Comparative genomics to the rescue: How complete is your plant genome sequence?
Comparative genomics to the rescue: How complete is your plant genome sequence?
Klaas Vandepoele
 
The use of blogs in teaching and learning literature in FL
The use of blogs in teaching and learning literature in FLThe use of blogs in teaching and learning literature in FL
The use of blogs in teaching and learning literature in FL
University of Limerick
 
Mediación escolar e implantación de un plan de mediación en un centro educativo
Mediación escolar e implantación de un plan de mediación en un centro educativoMediación escolar e implantación de un plan de mediación en un centro educativo
Mediación escolar e implantación de un plan de mediación en un centro educativo
apegon1
 
Lluvias en el norte 24.03.17
Lluvias en el norte 24.03.17Lluvias en el norte 24.03.17
Lluvias en el norte 24.03.17
Manuel Placido
 
kintone Café Akita Vol.1 対面開発
kintone Café Akita Vol.1 対面開発kintone Café Akita Vol.1 対面開発
kintone Café Akita Vol.1 対面開発
kintone papers
 
Gender gap in public speaking
Gender gap in public speakingGender gap in public speaking
Gender gap in public speaking
Shiftbalance
 
パケットが教えてくれた ルートサーバが 13個の理由
パケットが教えてくれた ルートサーバが 13個の理由パケットが教えてくれた ルートサーバが 13個の理由
パケットが教えてくれた ルートサーバが 13個の理由
@ otsuka752
 
Emergencias oncológicas (Diplomado UniRemington) Parte 4/6
Emergencias oncológicas (Diplomado UniRemington) Parte 4/6Emergencias oncológicas (Diplomado UniRemington) Parte 4/6
Emergencias oncológicas (Diplomado UniRemington) Parte 4/6
Mauricio Lema
 
Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6
Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6
Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6
Mauricio Lema
 
RUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkRUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践Smalltalk
Sho Yoshida
 
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...
Black Duck by Synopsys
 
Peter Allor - The New Era of Cognitive Security
Peter Allor - The New Era of Cognitive SecurityPeter Allor - The New Era of Cognitive Security
Peter Allor - The New Era of Cognitive Security
scoopnewsgroup
 
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...
BookNet Canada
 
Conference entreprise libérée
Conference entreprise libéréeConference entreprise libérée
Conference entreprise libérée
Christine Marsan
 
はじめてのgithub
はじめてのgithubはじめてのgithub
はじめてのgithub
Yasutaka Hamada
 
Ten query tuning techniques every SQL Server programmer should know
Ten query tuning techniques every SQL Server programmer should knowTen query tuning techniques every SQL Server programmer should know
Ten query tuning techniques every SQL Server programmer should know
Kevin Kline
 
Designing for Diversity in Design Orgs (Presentation)
Designing for Diversity in Design Orgs (Presentation)Designing for Diversity in Design Orgs (Presentation)
Designing for Diversity in Design Orgs (Presentation)
Eli Silva
 

Viewers also liked (20)

Rubyの拡張をCrystalで書いてみる
Rubyの拡張をCrystalで書いてみるRubyの拡張をCrystalで書いてみる
Rubyの拡張をCrystalで書いてみる
 
Opal - Ruby Style!! Ruby in the browser
Opal - Ruby Style!!  Ruby in the browserOpal - Ruby Style!!  Ruby in the browser
Opal - Ruby Style!! Ruby in the browser
 
Global Education and Skills Forum 2017 - Educating Global Citizens
Global Education and Skills Forum  2017 -  Educating Global CitizensGlobal Education and Skills Forum  2017 -  Educating Global Citizens
Global Education and Skills Forum 2017 - Educating Global Citizens
 
Comparative genomics to the rescue: How complete is your plant genome sequence?
Comparative genomics to the rescue: How complete is your plant genome sequence?Comparative genomics to the rescue: How complete is your plant genome sequence?
Comparative genomics to the rescue: How complete is your plant genome sequence?
 
The use of blogs in teaching and learning literature in FL
The use of blogs in teaching and learning literature in FLThe use of blogs in teaching and learning literature in FL
The use of blogs in teaching and learning literature in FL
 
Mediación escolar e implantación de un plan de mediación en un centro educativo
Mediación escolar e implantación de un plan de mediación en un centro educativoMediación escolar e implantación de un plan de mediación en un centro educativo
Mediación escolar e implantación de un plan de mediación en un centro educativo
 
Lluvias en el norte 24.03.17
Lluvias en el norte 24.03.17Lluvias en el norte 24.03.17
Lluvias en el norte 24.03.17
 
kintone Café Akita Vol.1 対面開発
kintone Café Akita Vol.1 対面開発kintone Café Akita Vol.1 対面開発
kintone Café Akita Vol.1 対面開発
 
Gender gap in public speaking
Gender gap in public speakingGender gap in public speaking
Gender gap in public speaking
 
パケットが教えてくれた ルートサーバが 13個の理由
パケットが教えてくれた ルートサーバが 13個の理由パケットが教えてくれた ルートサーバが 13個の理由
パケットが教えてくれた ルートサーバが 13個の理由
 
Emergencias oncológicas (Diplomado UniRemington) Parte 4/6
Emergencias oncológicas (Diplomado UniRemington) Parte 4/6Emergencias oncológicas (Diplomado UniRemington) Parte 4/6
Emergencias oncológicas (Diplomado UniRemington) Parte 4/6
 
Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6
Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6
Quimioterapia paliativa (Diplomado UniRemington) Parte 5c/6
 
RUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkRUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践Smalltalk
 
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...
 
Peter Allor - The New Era of Cognitive Security
Peter Allor - The New Era of Cognitive SecurityPeter Allor - The New Era of Cognitive Security
Peter Allor - The New Era of Cognitive Security
 
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...
 
Conference entreprise libérée
Conference entreprise libéréeConference entreprise libérée
Conference entreprise libérée
 
はじめてのgithub
はじめてのgithubはじめてのgithub
はじめてのgithub
 
Ten query tuning techniques every SQL Server programmer should know
Ten query tuning techniques every SQL Server programmer should knowTen query tuning techniques every SQL Server programmer should know
Ten query tuning techniques every SQL Server programmer should know
 
Designing for Diversity in Design Orgs (Presentation)
Designing for Diversity in Design Orgs (Presentation)Designing for Diversity in Design Orgs (Presentation)
Designing for Diversity in Design Orgs (Presentation)
 

Similar to How to write Ruby extensions with Crystal

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
 
Ruby Internals
Ruby InternalsRuby Internals
Ruby Internals
Burke Libbey
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
rstankov
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.
Workhorse Computing
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
.toster
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends旻琦 潘
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
Michael Koby
 
Introduction to the Ruby Object Model
Introduction to the Ruby Object ModelIntroduction to the Ruby Object Model
Introduction to the Ruby Object Model
Miki Shiran
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in php
CPD INDIA
 
Iq rails
Iq railsIq rails
Lightening Talk: Model Cat Can Haz Scope?
Lightening Talk: Model Cat Can Haz Scope?Lightening Talk: Model Cat Can Haz Scope?
Lightening Talk: Model Cat Can Haz Scope?evenellie
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1Jano Suchal
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em Ruby
Fabio Akita
 
JavaScript(Es5) Interview Questions & Answers
JavaScript(Es5)  Interview Questions & AnswersJavaScript(Es5)  Interview Questions & Answers
JavaScript(Es5) Interview Questions & Answers
Ratnala Charan kumar
 
Cocoa for Web Developers
Cocoa for Web DevelopersCocoa for Web Developers
Cocoa for Web Developers
georgebrock
 
C Sharp: Basic to Intermediate Part 01
C Sharp: Basic to Intermediate Part 01C Sharp: Basic to Intermediate Part 01
C Sharp: Basic to Intermediate Part 01Zafor Iqbal
 

Similar to How to write Ruby extensions with Crystal (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
 
Ruby Internals
Ruby InternalsRuby Internals
Ruby Internals
 
06 ruby variables
06 ruby variables06 ruby variables
06 ruby variables
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
 
05 ruby classes
05 ruby classes05 ruby classes
05 ruby classes
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Ruby training day1
Ruby training day1Ruby training day1
Ruby training day1
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
 
Introduction to the Ruby Object Model
Introduction to the Ruby Object ModelIntroduction to the Ruby Object Model
Introduction to the Ruby Object Model
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in php
 
Iq rails
Iq railsIq rails
Iq rails
 
Lightening Talk: Model Cat Can Haz Scope?
Lightening Talk: Model Cat Can Haz Scope?Lightening Talk: Model Cat Can Haz Scope?
Lightening Talk: Model Cat Can Haz Scope?
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em Ruby
 
JavaScript(Es5) Interview Questions & Answers
JavaScript(Es5)  Interview Questions & AnswersJavaScript(Es5)  Interview Questions & Answers
JavaScript(Es5) Interview Questions & Answers
 
Cocoa for Web Developers
Cocoa for Web DevelopersCocoa for Web Developers
Cocoa for Web Developers
 
C Sharp: Basic to Intermediate Part 01
C Sharp: Basic to Intermediate Part 01C Sharp: Basic to Intermediate Part 01
C Sharp: Basic to Intermediate Part 01
 

Recently uploaded

History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shopHistory+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
laozhuseo02
 
guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...
Rogerio Filho
 
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
3ipehhoa
 
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
3ipehhoa
 
How to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptxHow to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptx
Gal Baras
 
Latest trends in computer networking.pptx
Latest trends in computer networking.pptxLatest trends in computer networking.pptx
Latest trends in computer networking.pptx
JungkooksNonexistent
 
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesMulti-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Sanjeev Rampal
 
This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!
nirahealhty
 
Output determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CCOutput determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CC
ShahulHameed54211
 
1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...
JeyaPerumal1
 
test test test test testtest test testtest test testtest test testtest test ...
test test  test test testtest test testtest test testtest test testtest test ...test test  test test testtest test testtest test testtest test testtest test ...
test test test test testtest test testtest test testtest test testtest test ...
Arif0071
 
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
3ipehhoa
 
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptxLiving-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
TristanJasperRamos
 
ER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAEER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAE
Himani415946
 
BASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptxBASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptx
natyesu
 
The+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptxThe+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptx
laozhuseo02
 

Recently uploaded (16)

History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shopHistory+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
 
guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...
 
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
 
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
 
How to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptxHow to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptx
 
Latest trends in computer networking.pptx
Latest trends in computer networking.pptxLatest trends in computer networking.pptx
Latest trends in computer networking.pptx
 
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesMulti-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
 
This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!
 
Output determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CCOutput determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CC
 
1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...
 
test test test test testtest test testtest test testtest test testtest test ...
test test  test test testtest test testtest test testtest test testtest test ...test test  test test testtest test testtest test testtest test testtest test ...
test test test test testtest test testtest test testtest test testtest test ...
 
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
 
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptxLiving-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
 
ER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAEER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAE
 
BASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptxBASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptx
 
The+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptxThe+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptx
 

How to write Ruby extensions with Crystal

  • 1. How to write Ruby extensions with Crystal @gaar4ica
 Anna Shcherbinina
  • 3. 5 YO, a lot of stuff
  • 4. So, I like Ruby
  • 5. But, sometimes, I need my code to work faster
  • 6. def fibonacci(n) n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2) end Case of possible bottle neck
  • 7. Ruby has C bindings
  • 8. C is hard to learn and understand Static types Allocating 
 memory And tons of other complications for Ruby developer
  • 9. I’m ruby developer, I don’t want to write my code in C
  • 10. I’m ruby developer, I want to write my code in Ruby. But to be honest… Node.js NET OWL PDF XML Redis C++ Scala BASIC C#
  • 11. I’m ruby developer, I want to write my code in Ruby
  • 12. Also, I like Crystal
  • 14. Guess the language # define class Dog class Dog def initialize(breed, name) @breed = breed @name = name end def bark puts 'Ruff! Ruff!' end def display puts "I am of #{@breed} breed and my name is #{@name}" end end
 # make an object d = Dog.new('Labrador', 'Benzy')
  • 15. Crystal compiles to native code Spoiler about crystal
  • 16. So, I like Crystal
  • 17.
  • 21. C layer Link Crystal classes and methods to Ruby, so Ruby knows about them Translate 
 Ruby-types 
 to Crystal-types
  • 23. WUT? Compile to efficient 
 native code Statically 
 type-checked Ruby-inspired 
 syntax C bindings
  • 24. Web Frameworks • amatista • amethyst • kemal • moonshine Testing Search CacheDBDDBD Third-party 
 APIs Libs
  • 25. Ready for production or not? Web apps Microservice • maths calculation • small but heavy parts of projects What for
  • 26. Not so like ruby
  • 27. if @a # here @a can be nil end if @a.is_a?(String) # here @a is not guaranteed to be a String end if @a.responds_to?(:abs) # here @a is not guaranteed to respond to `abs` end The below doesn’t work with instance variables, class variables or global variables. Variables Not so like ruby
  • 28. To work with these, first assign them to a variable: if a = @a # here a can't be nil end # Second option: use `Object#try` found in the standard library @a.try do |a| # here a can't be nil end if (a = @a).is_a?(String) # here a is guaranteed to be a String end Variables Not so like ruby
  • 29. Classes and methods Not so like ruby Overloading Return types Visibility Finalize
  • 30. Macros Not so like ruby class Object macro def instance_vars_names : Array(String) {{ @type.instance_vars.map &.name.stringify }} end end class Person def initialize(@name, @age) end end person = Person.new "John", 30 person.instance_vars_names #=> ["name", "age"]
  • 31. Threads Not so like ruby def generate(chan) i = 2 loop do chan.send(i) i += 1 end end def filter(in_chan, out_chan, prime) loop do i = in_chan.receive if i % prime != 0 out_chan.send(i) end end end ch = Channel(Int32).new spawn generate(ch) 100.times do prime = ch.receive puts prime ch1 = Channel(Int32).new spawn filter(ch, ch1, prime) ch = ch1 end
  • 32. Benchmarking Time (s) Go Erlang Crystal Scala Ruby C Crystal Ruby C Crystal Ruby 4.084.082.21 27.92 6.025.08 41.73 6.426.091.971.48 Memory (Mb) Go Erlang Crystal Scala Ruby C Crystal Ruby C Crystal Ruby 162.40 1.400.40 115.50107.60 32.4030.00 1.505.3017.10 2.00 Threadring Binarytree Fast Threadring Binarytree Fast
  • 33. Back to case of possible bottle neck def fibonacci(n) n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2) end
  • 35. Less work for C Passing primitive data structures: • integer • string • boolean • float / decimal • etc. No allocation memory for complex data types Don’t do a lot of work for casting variables passed as attributes
  • 36. Ruby C API Entry point Then every C extension has to implement a function named Init_xxxxx (xxxxx being your extension’s name). It is being executed during the “require” of your extension. void Init_xxxxx() { // Code executed during "require" }
  • 37. Ruby C API Types Ruby C API defines a bunch of handful C constants defining standard Ruby objects: C Ruby Qnil nil Qtrue TRUE Qfalse FALSE rb_cObject Object rb_mKernel Kernel rb_cString String
  • 38. Ruby C API Declaring modules and classes // Creating classes // rb_define_class creates a new class named name // and inheriting from super. // The return value is a handle to the new class. VALUE rb_define_class(const char *name, VALUE super); // Creating modules // rb_define_module defines a module whose name // is the string name. // The return value is a handle to the module. VALUE rb_define_module(const char *name);
  • 39. Ruby C API Declaring methods // Creating a method // rb_define_method defines a new instance method in the class // or moduleklass. // The method calls func with argc arguments. // They differ in how they specify the name - rb_define_method // uses the constant string name void rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc); // rb_define_protected_method and rb_define_private_method are similar to rb_define_method, // except that they define protected and private methods, respectively. void rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc); void rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc);
  • 40. Ruby C API Ruby objects → C types // Convert Numeric to integer. long rb_num2int(VALUE obj); // Convert Numeric to unsigned integer. unsigned long rb_num2uint(VALUE obj); // Convert Numeric to double. double rb_num2dbl(VALUE); // Convert Ruby string to a String. VALUE rb_str_to_str(VALUE object); char* rb_string_value_cstr(volatile VALUE* object_variable);
  • 41. Ruby C API C types → Ruby objects // Convert an integer to Fixnum or Bignum. INT2NUM( int ); // convert an unsigned integer to Fixnum or Bignum. UINT2NUM( unsigned int ); // Convert a double to Float. rb_float_new( double ); // Convert a character string to String. rb_str_new2( char* ); // Convert a character string to ID (for Ruby function names, etc.). rb_intern( char* ); // Convert a character string to a ruby Symbol object. ID2SYM( rb_intern(char*) );
  • 42. Ruby C API Simple example # my_class.rb class MyClass def my_method(param1, param2) end end // my_class_ext.c static VALUE myclass_mymethod(VALUE rb_self, VALUE rb_param1, VALUE rb_param2) { // Code executed when calling my_method on an object of class MyClass } void Init_xxxxx() { // Define a new class (inheriting Object) in this module VALUE myclass = rb_define_class("MyClass", rb_cObject); // Define a method in this class, taking 2 arguments, // and using the C method "myclass_method" as its body rb_define_method(myclass, "my_method", myclass_mymethod, 2); }
  • 43. Ruby C API Simple example # my_class.rb class MyClass def my_method(param1, param2) end end // my_class_ext.c static VALUE myclass_mymethod(VALUE rb_self, VALUE rb_param1, VALUE rb_param2) { // Code executed when calling my_method on an object of class MyClass } void Init_xxxxx() { // Define a new class (inheriting Object) in this module VALUE myclass = rb_define_class("MyClass", rb_cObject); // Define a method in this class, taking 2 arguments, // and using the C method "myclass_method" as its body rb_define_method(myclass, "my_method", myclass_mymethod, 2); }
  • 44. Ruby C API Simple example # my_class.rb class MyClass def my_method(param1, param2) end end // my_class_ext.c static VALUE myclass_mymethod(VALUE rb_self, VALUE rb_param1, VALUE rb_param2) { // Code executed when calling my_method on an object of class MyClass } void Init_xxxxx() { // Define a new class (inheriting Object) in this module VALUE myclass = rb_define_class("MyClass", rb_cObject); // Define a method in this class, taking 2 arguments, // and using the C method "myclass_method" as its body rb_define_method(myclass, "my_method", myclass_mymethod, 2); }
  • 45. def fibonacci(n) n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2) end Back to case of possible 
 bottle neck And solution C
  • 46. A lib declaration groups C functions and types that belong to 
 a library. Crystal extension It’s easy lib CrRuby type VALUE = Void* $rb_cObject : VALUE end
  • 47. Every ruby object is treated as type VALUE in C. Crystal extension It’s easy lib CrRuby type VALUE = Void* $rb_cObject : VALUE end
  • 48. rb_cObject is a C constant defining standard Ruby Object class. Crystal extension It’s easy lib CrRuby type VALUE = Void* $rb_cObject : VALUE end
  • 49. lib CrRuby type VALUE = Void* $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE end A fun declaration inside a lib binds to a C function. We bind rb_num2int & rb_int2inum, to use it later. Crystal extension It’s easy
  • 50. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end Crystal extension It’s easy We bind rb_define_class & rb_define_method.
  • 51. def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end Our new and shiny fibonacci method in Crystal. def fibonacci(n) n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2) end Do you see the difference with implementation in Ruby? Crystal extension It’s easy
  • 52. Crystal extension It’s easy Let’s create a wrapper for this method, used for: • convert inbound Ruby-type parameter to Crystal; • convert outbound result back to Ruby type. def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end
  • 53. Crystal extension It’s easy Now we are done with our functions and C bindings. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end
  • 54. Crystal extension It’s easy Now we are done with our functions and C bindings. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end
  • 55. Crystal extension It’s easy Now we are done with our functions and C bindings. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end
  • 56. Crystal extension It’s easy Now we are done with our functions and C bindings. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end
  • 57. Crystal extension It’s easy We bind init function, the first one to be called. As you remember, a function named Init_xxxxx is being executed during the “require” of your extension. fun init = Init_cr_math end
  • 58. Crystal extension It’s easy Firstly, we start garbage collector. We need to invoke Crystal's "main" function, the one that initializes all constants and runs the top-level code. We pass 0 and null to argc and argv. fun init = Init_cr_math GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) end
  • 59. Crystal extension It’s easy We define class CrMath. fun init = Init_cr_math GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject) CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1) end
  • 60. Crystal extension It’s easy We define class CrMath. Attach method fibonacci to class. fun init = Init_cr_math GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject) CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1) end
  • 61. Crystal extension Ready to compile We have Crystal library with C bindings. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end fun init = Init_cr_math GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject) CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1) end
  • 62. Crystal extension Ready to compile We have method fibonacci_cr and wrapper for it. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end fun init = Init_cr_math GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject) CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1) end
  • 63. Crystal extension Ready to compile We have entry point. lib CrRuby type VALUE = Void* type METHOD_FUNC = VALUE, VALUE -> VALUE $rb_cObject : VALUE fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE fun rb_define_class(name: UInt8*, super: VALUE) : VALUE fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32) end def fibonacci_cr_wrapper(self : CrRuby::VALUE, value : CrRuby::VALUE) int_value = CrRuby.rb_num2int(value) CrRuby.rb_int2inum(fibonacci_cr(int_value)) end def fibonacci_cr(n) n <= 1 ? n : fibonacci_cr(n - 1) + fibonacci_cr(n - 2) end fun init = Init_cr_math GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) cr_math = CrRuby.rb_define_class("CrMath", CrRuby.rb_cObject) CrRuby.rb_define_method(cr_math, "fibonacci", ->fibonacci_cr_wrapper, 1) end
  • 64. Crystal extension Ready to compile Makefile CRYSTAL = crystal UNAME = "$(shell uname -ms)" LIBRARY_PATH = $(shell brew --prefix crystal-lang)/embedded/lib TARGET = cr_math.bundle $(TARGET): cr_math.o $(CC) -bundle -L$(LIBRARY_PATH) -o $@ $^ cr_math.o: cr_math.cr $(CRYSTAL) build --cross-compile $(UNAME) $<
  • 65. $ irb 2.1.6 :001 > require './cr_math' => true 2.1.6 :002 > CrMath.new.fibonacci(20) => 6765 Crystal extension Using in Ruby
  • 66. # benchmark.rb require 'benchmark' require './cr_math' # We have compiled cr_math.bundle require './rb_math' iterations = 10_000 number = 20 Benchmark.bm do |bm| bm.report("rb") do iterations.times { RbMath.new.fibonacci(number) } end bm.report("cr") do iterations.times { CrMath.new.fibonacci(number) } end end # rb_math.rb class RbMath def fibonacci(n) return n if n <= 1 fibonacci(n - 1) + fibonacci(n - 2) end end Crystal extension Benchmarking
  • 67. # benchmark.rb require 'benchmark' require './cr_math' # We have compiled cr_math.bundle require './rb_math' iterations = 10_000 number = 20 Benchmark.bm do |bm| bm.report("rb") do iterations.times { RbMath.new.fibonacci(number) } end bm.report("cr") do iterations.times { CrMath.new.fibonacci(number) } end end # rb_math.rb class RbMath def fibonacci(n) return n if n <= 1 fibonacci(n - 1) + fibonacci(n - 2) end end Crystal extension Benchmarking
  • 68. $ ruby benchmark.rb user system total real rb 10.270000 0.030000 10.300000 ( 10.314595) cr 0.460000 0.000000 0.460000 ( 0.464087) Crystal extension Benchmarking Ta-Da!