This document discusses how to write Ruby extensions using the Crystal programming language. Crystal compiles to efficient native code and has static typing like C, but with a Ruby-like syntax. The document explains how to define Crystal classes and methods, bind them to Ruby using C bindings, and compile the extension so it can be required from Ruby. Key points covered include declaring modules and functions in a C library, converting between Ruby and Crystal types, defining Ruby classes and methods from Crystal, and initializing the extension so it integrates with Ruby. The goal is to leverage Crystal's performance while still writing code in a Ruby-like way using the same interfaces as a C extension.
Global Education and Skills Forum 2017 - Educating Global CitizensEduSkills OECD
Andreas Schleicher - Director for the Directorate of Education and Skills, OECD
Each year the Global Education & Skills Forum brings together world leaders from the public, private and social sectors seeking solutions to achieving education, equity and employment for all.
Estimados amigos, las lluvias por obra de los vientos del norte y del oeste serán fuerte este sábado y domingo en la costa pero mas en la sierra(huaycos) Alertar no es alarmar!
Historically, women have been silenced. No wonder now it is harder to see gender balanced conferences or panels.
Here are a few resources to help you as a speaker or as a conference organizer to shift the speaker gender gap!
Open Source Insight: CVE-2017-2636 Vuln of the Week & UK National Cyber Secur...Black Duck by Synopsys
Seldom a month goes by where the NVD entries don’t break 1,000, and March 2017 is no exception. The vulnerability of the week is CVE-2017-2636, a serious security flaw in Linux kernel that appears to have been around since 2009. More on that story follows.
Spiders, Chatbots, and the Future of Metadata: A look inside the BNC BiblioSh...BookNet Canada
BookNet’s BiblioShare database now holds over 2 million public records and counting – so what are we doing with all that bibliographic data? Or better yet: what aren’t we doing? Join Tim as he demonstrates a few in-progress tools and blue-sky possibilities that put all that data to good use.
Ten query tuning techniques every SQL Server programmer should knowKevin Kline
From the noted database expert and author of 'SQL in a Nutshell' - SELECT statements have a reputation for being very easy to write, but hard to write very well. This session will take you through ten of the most problematic patterns and anti-patterns when writing queries and how to deal with them all. Loaded with live demonstrations and useful techniques, this session will teach you how to take your SQL Server queries mundane to masterful.
Designing for Diversity in Design Orgs (Presentation)Eli Silva
We all want more diversity in tech. We rarely acknowledge that the experience of inclusion is the product of Org Design. Presented at O'Reilly Design Conference with Molly Beyer, #OReillyDesign, these slides share some practical tips and advice on increasing diversity through applied design thinking. Learn how to empathize and ideate in response to real needs instead of getting people to 'hack a hairdryer'.
Object Trampoline: Why having not the object you want is what you need.Workhorse Computing
Overview of Trampoline Objects in Perl with examples for lazy construction, lazy module use, added sanity checks. This version includes corrections from the original presented at OSCON 2013 and comments.
Attributes Unwrapped: Lessons under the surface of active record.toster
Ведущий разработчик Ruby on Rails (Rails Core member) Джон Лейтон не так давно работал над совершенствованием реализации работы с атрибутами в Active Record. Он расскажет о своем опыте работы над важной для производительности областью Rails, даст советы и расскажет о техниках, которые могут быть применены к собственным приложениям слушателей.
Говоря о будущем, Джон также расскажет о своих идеях по изменению API работы с атрибутами в лучшую сторону; эти изменения могут появиться в Rails 4.0.
You've learned to program in Ruby, but now you want to start learning about how to move beyond the language basics and make use of some of the dynamic parts of the Ruby language. We'll cover that a bit here.
TDC 2012 - Patterns e Anti-Patterns em RubyFabio Akita
Palestra apresentada no The Developers Conference 2012 em São Paulo. Explicação sobre Patterns e Anti-Patterns em Ruby para quem está iniciando a aprender a linguagem.
My talk at BarCamp London 5: An introduction to Cocoa development and how web developers can cheat.
Source code to go with this presentation is available here: http://georgebrock.com/conferences/barcamplondon5
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesSanjeev Rampal
Talk presented at Kubernetes Community Day, New York, May 2024.
Technical summary of Multi-Cluster Kubernetes Networking architectures with focus on 4 key topics.
1) Key patterns for Multi-cluster architectures
2) Architectural comparison of several OSS/ CNCF projects to address these patterns
3) Evolution trends for the APIs of these projects
4) Some design recommendations & guidelines for adopting/ deploying these solutions.
This 7-second Brain Wave Ritual Attracts Money To You.!nirahealhty
Discover the power of a simple 7-second brain wave ritual that can attract wealth and abundance into your life. By tapping into specific brain frequencies, this technique helps you manifest financial success effortlessly. Ready to transform your financial future? Try this powerful ritual and start attracting money today!
1.Wireless Communication System_Wireless communication is a broad term that i...JeyaPerumal1
Wireless communication involves the transmission of information over a distance without the help of wires, cables or any other forms of electrical conductors.
Wireless communication is a broad term that incorporates all procedures and forms of connecting and communicating between two or more devices using a wireless signal through wireless communication technologies and devices.
Features of Wireless Communication
The evolution of wireless technology has brought many advancements with its effective features.
The transmitted distance can be anywhere between a few meters (for example, a television's remote control) and thousands of kilometers (for example, radio communication).
Wireless communication can be used for cellular telephony, wireless access to the internet, wireless home networking, and so on.
ER(Entity Relationship) Diagram for online shopping - TAEHimani415946
https://bit.ly/3KACoyV
The ER diagram for the project is the foundation for the building of the database of the project. The properties, datatypes, and attributes are defined by the ER diagram.
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')
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
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
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!