Rabbit Slide Show

How to create bindings 2016

2016-09-09

Description

This talk describes how to create Ruby bindings of a C library. It's the latest information in 2016.

Text

Page: 1

Ruby bindings 2016
How to create bindings 2016
Kouhei Sutou
ClearCode Inc.
RubyKaigi 2016
2016-09-09
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 2

Acknowledgment
感謝
@SoManyHs and @drbrain
They fixed English
in this slide
@RubyKaigi 2016 Official Party
昨日のパーティーで英語をチェックしてくれた!ありがとう!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 3

Silver
Silver sponsor
sponsor

Page: 4

Goal
目標
You become
a new bindings developer
あなたが新しくバインディング開発者になること
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 5

Bindings?
バインディングとは
✓ Glue of
(mainly)
主にCとRubyをつなぐもの
C and Ruby
✓ You can use features implemented
in C from Ruby
Cで実装された機能をRubyから使える
✓ e.g.: Socket, OpenSSL, YAML, ...
例:ソケット、OpenSSL、YAML…
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 6

Bindings
バインディング
Can't use...
Can use socket!
Error
require "socket" Ruby require "socket"
Bindings
socket(2)
Ruby bindings 2016 - How to create bindings 2016
Bindings
C
socket(2)
Powered by Rabbit 2.2.0

Page: 7

Why should I learn?
なんでバインディング開発者になるの?
✓ To use Ruby in more cases
Rubyをもっといろんな場面で使うため
✓ e.g.:
Machine leaning, multimedia, full
text search, cipher and so on
例:機械学習、画像・動画・音声処理、全文検索、暗号
✓ Can use existing features in
Ruby through bindings
バインディングがあると既存のいい機能をRubyで使える
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 8

Incr. bindings developer
バインディング開発者が増えるといいな
✓ Why do I become a bindings
developer?
バインディング開発者になりませんか?
✓ To expand use cases of Ruby!
Rubyを使えるケースを増やすために!
✓ Not just a user for
provided features
提供された機能を使う1ユーザーではなく
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 9

Summary
概要
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. Hand
by
FFI
lib
ffi GI☆
lib
ffi
Gene- Hand
rate Gene-
rate
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 10

Demo
デモ
Make powerful
auto generated
bindings
自動生成されたバインディングがいかに強力か
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 11

What is ext?
拡張ライブラリーってなに?
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. Hand
by
FFI
lib
ffi GI☆
lib
ffi
Gene- Hand
rate Gene-
rate
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 12

Extension library
拡張ライブラリーとは
✓ Ruby library written in C
Cで書かれたRuby用ライブラリー
✓ Most bindings are ext lib
多くのバインディングは拡張ライブラリーとして実装
✓ openssl is ext lib and bindings
oepnsslは拡張ライブラリーでバインディング
✓ Exc.: stringio is ext lib but...
例外:stringioは拡張ライブラリーだが…
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 13

Ext lib and bindings
拡張ライブラリーとバインディング
Extension library
Bindings
openssl stringio
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 14

What is libffi?
libffiってなに?
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. Hand
by
FFI
lib
ffi GI☆
lib
ffi
Gene- Hand
rate Gene-
rate
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 15

libffi and FFI: 1
libffiとFFIとは:1
✓ libffi: Library to impl. FFI
FFIを実現するためのライブラリー
✓ Foreign Function Interface
✓ Generally:
All APIs to impl. bindings
一般的にはバインディングを実装するためのすべての
API
✓ Ruby doesn't use "FFI" term
Rubyでは「FFI」という単語を使わない
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 16

libffi and FFI: 2
libffiとFFIとは:2
✓ Ruby FFI
✓ Library based on libffi
libffiを使ったライブラリー
✓ Provides Ruby API
to implement bindings
バインディングを実装するためのRubyのAPIを提供
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 17

libffi and bindings
libffiとバインディング
Bindings
attach_function :rand, [], :int
Ruby
libffi based Ruby API
libffi
C
rand(3)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 18

Impl. language
実装言語
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. C
lang
C+α
FFI
lib
ffi GI☆
lib
ffi
Ruby Ruby
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 19

Ext impl. by
拡張ライブラリーの実装方法
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. Hand
by
FFI
lib
ffi GI☆
lib
ffi
Gener Hand
ate Gene-
rate
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 20

Ext impl. by: Target
拡張ライブラリーの実装方法:対象
/* hello.h */
#pragma once
typedef struct hello_t Hello;
Hello
*hello_new
(void);
void
hello_free
(Hello *hello);
const char *hello_message(Hello *hello);
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 21

Ext impl. by hand
手動での拡張ライブラリーの実装
Implemented in C by hand
Use C API provided by Ruby
libhello
Bindings
Ruby bindings 2016 - How to create bindings 2016
Ruby
Powered by Rabbit 2.2.0

Page: 22

Ext impl. by hand
手動での拡張ライブラリーの実装
https://github.com/kou/rabbit-slide-kou-rubykaigi-2016/
blob/master/c-api/bindings/hello.c
#include <ruby.h>
#include <hello.h>
static void
rb_hello_free(void *data)
{
Hello *hello = data;
hello_free(hello);
}
static const rb_data_type_t rb_hello_type = {
"Hello",
{
NULL,
rb_hello_free,
NULL,
},
NULL,
NULL,
RUBY_TYPED_FREE_IMMEDIATELY,
};
static VALUE
rb_hello_alloc(VALUE klass)
{
return TypedData_Wrap_Struct(klass, &rb_hello_type, NULL);
}
static VALUE
rb_hello_initialize(VALUE self)
{
Hello *hello;
hello = hello_new();
DATA_PTR(self) = hello;
return Qnil;
}
static VALUE
rb_hello_message(VALUE self)
{
Hello *hello;
const char *message;
TypedData_Get_Struct(self, Hello, &rb_hello_type, hello);
message = hello_message(hello);
return rb_str_new_cstr(message);
}
void
Init_hello(void)
{
VALUE hello;
hello = rb_define_class("Hello", rb_cData);
rb_define_alloc_func(hello, rb_hello_alloc);
rb_define_method(hello, "initialize", rb_hello_initialize, 0);
rb_define_method(hello, "message", rb_hello_message, 0);
}
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 23

Ext impl. by generation
自動生成での拡張ライブラリーの実装
Generated by SWIG
Use C API provided by Ruby
Bindings
libhello
Ruby
SWIG
hello.i
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 24

Ext impl. by generation
自動生成での拡張ライブラリーの実装
✓ SWIG can generate impl.
Simplified Wrapper and Interface Generator
SWIGで実装を生成できる
✓ A user
✓ TensorFlow: A library for machine
intelligence
TensorFlow:機械知能のライブラリー
Used to generate Python bindings
Pythonバインディングを生成するために使用
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 25

Ext impl. by SWIG
SWIGでの拡張ライブラリーの実装
// swig -ruby hello.i -> hello_wrap.c
%module hello
%{
#include <hello.h>
%}
%include <hello.h>
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 26

Use ext by SWIG
SWIGで作った拡張ライブラリーを使う
irb(main):001:0> require "hello"
=> true
irb(main):002:0> hello = Hello.hello_new
=> #<SWIG::TYPE_p_hello_t:0x000...>
irb(main):003:0> Hello.hello_message(hello)
=> "Hello"
irb(main):004:0> Hello.hello_free(hello)
=> nil
# Raw C API... :<
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 27

By SWIG again
SWIGでもう一度
%module hello
%{#include <hello.h>%}
typedef struct hello_t {
%extend {
hello_t() {return hello_new();}
~hello_t() {hello_free($self);}
const char *message() {return hello_message($self);}
}
} Hello;
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 28

Use again
もう一度使う
irb(main):001:0> require "hello"
=> true
irb(main):002:0> hello = Hello::Hello.new
=> #<Hello::Hello:0x000...>
irb(main):003:0> hello.message
=> "Hello"
# Object oriented API!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 29

Wrap up1: Ext
まとめ1:拡張ライブラリー
✓ By hand: Needs more work
手動:たくさん書かないといけない
✓ By generation: Less work
生成:書くことが少ない
✓ Needs more work for easy use
使いやすいAPIにするにはたくさん書かないといけない
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 30

Wrap up2: Ext
まとめ2:拡張ライブラリー
✓ On maintenance
e.g.: New functions, enums
メンテナンス時:(例:新しい関数・列挙値が追加され
た)
✓ By hand: Needs more work
手動:追加作業あり
✓ By generation: No more work
(But the bindings may not be easy to use)
生成:(使いやすくないけど)追加作業なし
This is a large benefit!
これは大きな利点!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 31

libffi impl. by
libffiベースでの実装方法
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. Hand
by
FFI
lib
ffi GI☆
lib
ffi
Gene- Hand
rate Gener
ate
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 32

libffi impl. by hand
手動でのlibffiベースの実装
Implemented in Ruby by hand
Use Ruby API provided by Ruby FFI
libhello
Bindings
Ruby bindings 2016 - How to create bindings 2016
Ruby
Powered by Rabbit 2.2.0

Page: 33

libffi impl. by hand
手動でのlibffiベースの実装
require "ffi"
module LibHello
extend FFI::Library
ffi_lib "../../libhello/lib/libhello.so"
attach_function :hello_new, [], :pointer
attach_function :hello_message, [:pointer], :string
attach_function :hello_free, [:pointer], :void
end
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 34

Use libffi impl. by hand
手動でのlibffiベースの実装を使う
irb(main):001:0> require "hello"
=> true
irb(main):002:0> hello = LibHello.hello_new
=> #<FFI::Pointer address=0x00000002b07ef0>
irb(main):003:0> LibHello.hello_message(hello)
=> "Hello"
irb(main):004:0> LibHello.hello_free(hello)
=> nil
# Raw C API... :<
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 35

Wrap FFI impl. 1
FFIでの実装をラップ1
class Hello
def initialize
hello = LibHello.hello_new
hello_free = LibHello.method(:hello_free)
@hello =
FFI::AutoPointer.new(hello, hello_free)
end
end
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 36

Wrap FFI impl. 2
FFIでの実装をラップ2
class Hello
def message
LibHello.hello_message(@hello)
end
end
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 37

Use wrapped impl.
ラップした実装を使う
irb(main):001:0> require "hello"
=> true
irb(main):002:0> hello = Hello.new
=> #<Hello:0x000...>
irb(main):003:0> hello.message
=> "Hello"
# Object oriented API!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 38

libffi impl. by gen.
自動生成でのlibffiベースの実装
(*) gi = gobject-introspection
Generated by gi(*) gem at runtime
libhello
GObject
wrapper
libghello
g-ir-compiler
Bindings
Hello.typelib
Annotation
Ruby bindings 2016 - How to create bindings 2016
Ruby
gi gem
gi
Powered by Rabbit 2.2.0

Page: 39

libffi impl. by gen.
自動生成でのlibffiベースの実装
require "gi"
Hello = GI.load("Hello")
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 40

Use libffi impl. by gen.
自動生成でのlibffiベースの実装を使う
irb(main):001:0> require "hello"
=> true
irb(main):002:0> hello = Hello::Hello.new
=> #<Hello::Hello:0x2a9de98 ptr=0x2ecd540>
irb(main):003:0> hello.message
=> "Hello"
# Object oriented API!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 41

Wrap up1: libffi
まとめ1:libffi
✓ By hand: Needs more work
手動:たくさん書かないといけない
✓ Needs more work for easy use
使いやすいAPIにするにはさらに書かないといけない
✓ By generation: Less work
生成:書くことが少ない
✓ No more work for easy use
しかも使いやすいAPIになる
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 42

Wrap up2: libffi
まとめ2:libffi
✓ On maintenance
e.g.: New functions, enums
メンテナンス時:(例:新しい関数・列挙値が追加され
た)
✓ By hand: Needs more work
手動:追加作業あり
✓ By generation: No more work
生成:追加作業なし
This is a large benefit!
これは大きな利点!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 43

Impl. by generation
生成ベースでの実装方法
Base
Tech
Ext★ SWIG
Ext
Ext
Impl. Hand
by
FFI
lib
ffi GI☆
lib
ffi
Gener Hand
ate Gener
ate
★ Extension library(拡張ライブラリー)
☆ GObject Introspection: Recommended(オススメ)
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 44

SWIG⇔GI: When
SWIG⇔GI:生成タイミング
✓ When are bindings generated?
バインディングの生成タイミング
✓ On build⇔Runtime
ビルド時⇔実行時
✓ SWIG: Need to build for new ver.
新しいバージョンがでたらリビルドが必要
✓ GI: No more work for new ver.
新しいバージョンがでても追加作業なし
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 45

SWIG⇔GI: Maintenance
SWIG⇔GI:メンテナンス
✓ SWIG: Maintain .i file for
each language binding
各言語バインディング用に.iファイルをメンテナンス
✓ GI: Maintain annotations for
all language bindings
全言語バインディング用にアノテーションをメンテナンス
✓ We can work together with other
language binding maintainers
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 46

SWIG: Overview (reprise)
SWIG:概要(再掲)
Generated by SWIG
Use C API provided by Ruby
Bindings
libhello
Ruby
SWIG
hello.i
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 47

SWIG: Maintenance
SWIG:メンテナンス
Generated by SWIG
Use C API provided by Ruby
Bindings
libhello
Ruby
Ruby binding
maintainers maintain
SWIG
hello.i
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 48

GI: Overview (reprise)
GI:概要(再掲)
(*) gi = gobject-introspection
Generated by gi(*) gem at runtime
libhello
GObject
wrapper
libghello
g-ir-compiler
Bindings
Hello.typelib
Annotation
Ruby bindings 2016 - How to create bindings 2016
Ruby
gi gem
gi
Powered by Rabbit 2.2.0

Page: 49

GI: Maintenance
GI:メンテナンス
(*) gi = gobject-introspection
Generated by gi(*) gem at runtime
GObject
wrapper
Bindings
Ruby
We can maintain with
library maintainers
g-ir-compiler
gem
and other gi language
Hello.typelib
binding maintainers
gi
Annotation
libhello
libghello
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 50

Wrap up1
まとめ1
✓ Bindings: Glue of C and Ruby
バインディング:主にCとRubyをつなぐもの
✓ You can use features implemented
in C from Ruby
Cで実装された機能をRubyから使える
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 51

Wrap up2
まとめ2
✓ Bindings increase cases that
Ruby can be used
バインディングはRubyを使えるケースを増やす
✓ Because they provide existing
good features to Ruby
バインディングは既存のよい機能をRubyで使えるように
するから
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 52

Wrap up3
まとめ3
✓ Recommend GI based bindings
GIベースのバインディングがオススメ
✓ For easy maintenance
メンテンナンスしやすいから
✓ For easy to use API
使いやすいAPIになるから
GI: GObject Introspection
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 53

Wrap up4
まとめ4
Let's become a
bindings
developer!
バインディング開発者になろう!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 54

Advertisement
✓ OSS Gate
宣伝
✓ Helps people who want to be an
OSS developer (but not yet)
OSS開発者になりたいけど一歩踏み出せていない人を支
援
✓ ClearCode booth (クリアコードブース)
✓ You can discus about OSS Gate and
more technical details
OSS Gateやもっと技術的な話や雑談をできる
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 55

Wrap up (reprise)
まとめ(再掲)
Let's become a
bindings
developer!
バインディング開発者になろう!
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Page: 56

Things not covered
話さなかったこと
✓ Bindings are difficult to
install on Win. Any idea?
Windowsでインストールが大変。どうすれば?
✓ Performance・Annotation
性能・アノテーション
✓ Details of each binding's
create method
それぞれのバインディング作成方法の詳細
Ruby bindings 2016 - How to create bindings 2016
Powered by Rabbit 2.2.0

Other slides

Apache Arrow
2017-06-13
Apache Arrow
2017-05-28
Mroonga!
2015-10-30