rabbit-slide-kou-rubykaigi-2016 2016.9.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rabbit +1 -0
- data/README.rd +24 -0
- data/Rakefile +17 -0
- data/a.md +48 -0
- data/config.yaml +23 -0
- data/how-to-create-bindings-2016.rab +421 -0
- data/images/bindings.svg +790 -0
- data/images/clear-code-silver-sponsor.png +0 -0
- data/images/extension-library-and-bindings.svg +219 -0
- data/images/libffi-and-bindings.svg +388 -0
- data/overview.md +51 -0
- data/pdf/rubykaigi-2016-how-to-create-bindings-2016.pdf +0 -0
- data/theme.rb +1 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b032ef54474e6fb2d6213f008397240691570368
|
4
|
+
data.tar.gz: 75d63b266c7db660d967f54ab5c7827ed490a8a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca2b829c46c709b8700c6a46cfae91de0598f0fc6914df855f1b79a64e92c0486b61d6e3c4e256d77086f6a7b4cee6950b495981f45ae7b3dcd6c70e064384ea
|
7
|
+
data.tar.gz: fd09c94ecb21cdd388c3c81f23d89e478b8a870f42e989d62a5eabeceadbca48c31af30f8f764c125e3f9425ee23988b5407587a77c073d64730e5b24c90b062
|
data/.rabbit
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
how-to-create-bindings-2016.rab
|
data/README.rd
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
= How to create bindings 2016
|
2
|
+
|
3
|
+
This talk describes how to create Ruby bindings of a C library. It's the latest information in 2016.
|
4
|
+
|
5
|
+
== For author
|
6
|
+
|
7
|
+
=== Show
|
8
|
+
|
9
|
+
rake
|
10
|
+
|
11
|
+
=== Publish
|
12
|
+
|
13
|
+
rake publish
|
14
|
+
|
15
|
+
== For viewers
|
16
|
+
|
17
|
+
=== Install
|
18
|
+
|
19
|
+
gem install rabbit-slide-kou-rubykaigi-2016
|
20
|
+
|
21
|
+
=== Show
|
22
|
+
|
23
|
+
rabbit rabbit-slide-kou-rubykaigi-2016.gem
|
24
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rabbit/task/slide"
|
2
|
+
|
3
|
+
# Edit ./config.yaml to customize meta data
|
4
|
+
|
5
|
+
spec = nil
|
6
|
+
Rabbit::Task::Slide.new do |task|
|
7
|
+
spec = task.spec
|
8
|
+
spec.files += Dir.glob("images/*.*")
|
9
|
+
# spec.files -= Dir.glob("private/**/*.*")
|
10
|
+
spec.add_runtime_dependency("rabbit-theme-clear-code")
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Tag #{spec.version}"
|
14
|
+
task :tag do
|
15
|
+
sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
|
16
|
+
sh("git", "push", "--tags")
|
17
|
+
end
|
data/a.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# [Ruby][会社] クリアコード:RubyKaigi 2016にスピーカー・スポンサーとして参加予定
|
2
|
+
|
3
|
+
9月8日から10日の3日間[RubyKaigi 2016](http://rubykaigi.org/2016/)が開催されます。
|
4
|
+
|
5
|
+
クリアコードは例年RubyKaigiのスポンサーをしています。去年の[RubyKaigi 2015のスポンサー](20151209)に引き続き、[RubyKaigi 2016もスポンサー](http://rubykaigi.org/2016/sponsors#clear-code)になりました。今年はブースを出します。ブースでは[OSS Gate](https://oss-gate.doorkeeper.jp/)とクリアコード自体のことを紹介する予定です。クリアコードが気になる人は遊びに来てください。
|
6
|
+
|
7
|
+
また、須藤と沖元がスピーカーとして話します。どちらも[2日目の9月9日](http://rubykaigi.org/2016/schedule/#sep09)です。須藤は[10:30からのセッション](http://rubykaigi.org/2016/presentations/ktou.html)で最新のバインディングの作り方について話します。沖元は[14:20からのセッション](http://rubykaigi.org/2016/presentations/okkez.html)でRubyリファレンスマニュアルについて話します。
|
8
|
+
|
9
|
+
ところで、8月21日にリリースされた[Rubyist Magazine 0054号](http://magazine.rubyist.net/?0054)では[東京 Ruby 会議 11 運営記録](http://magazine.rubyist.net/?0054-TokyoRubyKaigi11OrganizeReport)がよかったです。この記事の中に事前インタビューの目的が書いてあります。4つ目の目的として「発表者に事前インタビューすることで、発表の内容を事前に考えて貰う」が挙がっています。RubyKaigi 2016では事前インタビューはありませんが、ここに発表内容を事前にまとめることで同じ目的を達成できるはずです。ということで、須藤の発表内容を紹介します。
|
10
|
+
|
11
|
+
## 2016年のバインディングの作り方
|
12
|
+
|
13
|
+
バインディングとはRuby以外の言語(主にC言語とC++言語)で実装された機能をRubyで使うためのライブラリーです。バインディングを使うと、Rubyでその機能を実装しなくてもその機能を使えるようになるため、短時間で高品質の機能を手に入れ(られることがあり)ます。また、C言語での実装はRubyでの実装よりも10倍100倍速いことがざらにあるので、性能面でも有利です。画像処理・動画処理・音声処理・全文検索・機械学習・統計処理・暗号処理などは実装コスト・性能の両面からバインディングを利用して既存実装を活用するのが向いている分野です。
|
14
|
+
|
15
|
+
というような背景があり、RubyをWebだけでなく様々な分野で活用するためにはバインディングは重要です。そんなバインディングの作り方を紹介するのが須藤の話です。
|
16
|
+
|
17
|
+
バインディングを作るために使える仕組みが拡張ライブラリーです。拡張ライブラリーはC言語で実装された機能をRubyに組み込む仕組みです。C言語で既存の機能をラップする拡張ライブラリーを作ることでバインディングになります。
|
18
|
+
|
19
|
+
拡張ライブラリーの難点の1つに「インストールするためにはCコンパイラーが必要なこと」があります。拡張ライブラリーを使うためにはコンパイルする必要があるため、Cコンパイラーがないと拡張ライブラリーを使えません。GNU/LinuxやBSD系などCコンパイラーを用意しやすいOSもあればそうでないOSもあります。たとえば、WindowsではCコンパイラーを用意することの敷居が高く、インストールが難しいです。
|
20
|
+
|
21
|
+
この問題を解決する方法としてfat gemというやり方があります。これはgemの中にビルド済みバイナリーを入れるというやり方です。こうすることにより、ユーザーの環境にCコンパイラーがなくても拡張ライブラリーを使えるようになります。fat gemはWindowsユーザー向けだけに用意すればよいです。Windows以外のよく使われている環境ではCコンパイラーを用意することは比較的簡単だからです。
|
22
|
+
|
23
|
+
拡張ライブラリーの難点はもう1つあります。バインディング対象の機能数に応じて実装コストがあがる点です。Rubyが拡張ライブラリー用に提供しているAPIは比較的使いやすいため、拡張ライブラリーとしてバインディングを作ることは技術的にそれほど難しくありません。ただし、対象機能を1つずつラップするため、対象機能が多いとその分手間がかかるのです。
|
24
|
+
|
25
|
+
この難点を解決する方法としてバインディングを生成する方法があります。拡張ライブラリーによるバインディングの実装にはある程度パターンがあるので生成することができるのです。[SWIG](http://www.swig.org/)というツールはそれを実現するためのツールです。
|
26
|
+
|
27
|
+
SWIGを使うと(多くの場合は)少ない記述でバインディング用の拡張ライブラリーのコードを生成できます。これで、少ない手間でたくさんの機能のバインディングを作ることができます。ただ、SWIGを使った場合でもいくつか難点があります。
|
28
|
+
|
29
|
+
SWIGも拡張ライブラリーを使ったバインディングなのでインストールが難しい問題があります。これはfat gemというやり方で解決できるのは前述のとおりです。しかし、SWIGを使った場合は別の問題もあります。インストール時にCコンパイラーとSWIGが必要になる点です。通常、SWIGはシステムにインストールされていないので別途インストールする必要があります。インストール時にSWIGが必要なくする方法もあります。SWIGで生成した拡張ライブラリーのコードをgemに含める方法です。こうすることでインストール時にSWIGは必要なくなります。ただし、gemに含めたときに生成した機能しか含まれません。gemに含めたときの対象ライブラリーはバージョン1で、ユーザーがインストールしようとしたときはバージョン2になっていた、という場合、バージョン2で追加された機能は使えない、ということです。
|
30
|
+
|
31
|
+
性能面でも幾分オーバーヘッドがあります。手書きでシンプルに実装したバインディングとSWIGで自動生成したバインディングではシンプルに実装したバインディングの方が高速です。バインディングのメソッドを大量に呼び出す(何万回とか)場合は影響があるでしょう。
|
32
|
+
|
33
|
+
これまでのバインディングの作成方法ではインストールの難しさが難点としてでていました。これはC言語を使っていることが原因です。つまり、C言語を使わずにバインディングを作れればインストールが簡単になります。その方法はFFI(Foreign Function Interface)を使う方法です。なお、最近のRubyで使えるFFIの実装はすべてlibffiというライブラリーを使っています。
|
34
|
+
|
35
|
+
FFIを使うとRubyでバインディングを書くことができます。拡張ライブラリーでやっていたことをRubyで書けるようになっただけで、1つずつ機能をラップしていかなければいけない点は変わりませんが、それをCではなくRubyで書けるようになることで書きやすくなっています。
|
36
|
+
|
37
|
+
バインディングにC言語を使わなくなったことによりバインディングのインストールは確かに簡単になるのですが、バインディングが動くためにはラップ対象のライブラリーは依然として必要です。そのため、Windowsユーザーがインストールしにくいという点はそれほど解決されていません。
|
38
|
+
|
39
|
+
また、バインディングを書く言語がCからRubyになっているので手間は減ってはいますが、対象の機能がたくさんあると結局手間なのは変わりません。
|
40
|
+
|
41
|
+
さらに、FFIを使うとSWIGを使ったときよりも性能が落ちます。
|
42
|
+
|
43
|
+
TODO
|
44
|
+
|
45
|
+
|
46
|
+
## まとめ
|
47
|
+
|
48
|
+
クリアコードは9月8日から10日にかけて開催されるRubyKaigi 2016にスピーカー・スポンサーとして参加します。この機会に多くの人と交流できることを期待しています。それでは、RubyKaigi 2016で会いましょう。
|
data/config.yaml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
id: rubykaigi-2016
|
3
|
+
base_name: how-to-create-bindings-2016
|
4
|
+
tags:
|
5
|
+
- rabbit
|
6
|
+
- ruby
|
7
|
+
- bindings
|
8
|
+
presentation_date: 2016-09-08
|
9
|
+
version: 2016.9.8.0
|
10
|
+
licenses:
|
11
|
+
- CC BY-SA 4.0
|
12
|
+
slideshare_id:
|
13
|
+
speaker_deck_id:
|
14
|
+
ustream_id:
|
15
|
+
vimeo_id:
|
16
|
+
youtube_id:
|
17
|
+
author:
|
18
|
+
markup_language: :rd
|
19
|
+
name: Kouhei Sutou
|
20
|
+
email: kou@clear-code.com
|
21
|
+
rubygems_user: kou
|
22
|
+
slideshare_user: kou
|
23
|
+
speaker_deck_user:
|
@@ -0,0 +1,421 @@
|
|
1
|
+
= Ruby bindings 2016
|
2
|
+
|
3
|
+
: subtitle
|
4
|
+
How to create bindings 2016
|
5
|
+
|
6
|
+
: author
|
7
|
+
Kouhei Sutou
|
8
|
+
: institution
|
9
|
+
ClearCode Inc.
|
10
|
+
: content-source
|
11
|
+
RubyKaigi 2016
|
12
|
+
: date
|
13
|
+
2016-09-08
|
14
|
+
: allotted-time
|
15
|
+
35m
|
16
|
+
: theme
|
17
|
+
.
|
18
|
+
|
19
|
+
= Silver sponsor
|
20
|
+
|
21
|
+
# img
|
22
|
+
# src = images/clear-code-silver-sponsor.png
|
23
|
+
# relative_height = 100
|
24
|
+
|
25
|
+
# == Slide properties
|
26
|
+
|
27
|
+
# : enable-title-on-image
|
28
|
+
# false
|
29
|
+
|
30
|
+
= Goal\n(('note:目標'))
|
31
|
+
|
32
|
+
(('tag:center'))
|
33
|
+
(('tag:large'))
|
34
|
+
You know about\n
|
35
|
+
how to create bindings
|
36
|
+
|
37
|
+
(('tag:center'))
|
38
|
+
(('note:バインディングの作り方を知ること'))
|
39
|
+
|
40
|
+
= Bindings?\n(('note:バインディングとは'))
|
41
|
+
|
42
|
+
* Glue of (('note:(mainly)')) C and Ruby\n
|
43
|
+
(('note:主にCとRubyをつなぐもの'))
|
44
|
+
|
45
|
+
* (('wait'))You can use features implemented in C from Ruby\n
|
46
|
+
(('note:Cで実装された機能をRubyから使える'))
|
47
|
+
|
48
|
+
* (('wait'))e.g.: Socket, OpenSSL, YAML, ...\n
|
49
|
+
(('note:例:ソケット、OpenSSL、YAML…'))
|
50
|
+
|
51
|
+
= Bindings\n(('note:バインディング'))
|
52
|
+
|
53
|
+
# image
|
54
|
+
# src = images/bindings.svg
|
55
|
+
# relative_height = 100
|
56
|
+
|
57
|
+
== slide properties
|
58
|
+
|
59
|
+
: enable-title-on-image
|
60
|
+
false
|
61
|
+
|
62
|
+
= But why do I know?\n(('note:でも、どうして知るといいの?'))
|
63
|
+
|
64
|
+
* (('wait'))To use Ruby in more cases\n
|
65
|
+
(('note:Rubyをもっといろんな場面で使うため'))
|
66
|
+
* e.g.: (('tag:x-small:Machine leaning, multimedia, full text search, cipher and so on'))\n
|
67
|
+
(('note:例:機械学習、画像・動画・音声処理、全文検索・暗号'))
|
68
|
+
* (('wait'))We can use existing good features in Ruby by bindings\n
|
69
|
+
(('note:バインディングがあると既存のいい機能をRubyで使える'))
|
70
|
+
|
71
|
+
= Incr. bindings developer\n(('note:バインディング開発者が増えるといいな'))
|
72
|
+
|
73
|
+
* How about becoming a bindings developer?\n
|
74
|
+
(('note:バインディング開発者になりませんか?'))
|
75
|
+
* (('wait'))To expand Ruby use cases!\n
|
76
|
+
(('note:Rubyの適用可能領域を増やすために!'))
|
77
|
+
* (('wait'))Not just an user for\n
|
78
|
+
provided features\n
|
79
|
+
(('note:提供された機能を使う1ユーザーではなく'))
|
80
|
+
|
81
|
+
= Summary\n(('note:概要'))
|
82
|
+
|
83
|
+
# RT
|
84
|
+
|
85
|
+
, Ext★, SWIG, FFI, GI☆
|
86
|
+
|
87
|
+
Base\nTech, Ext, Ext, lib\nffi, lib\nffi
|
88
|
+
Impl.\nby, Hand, Gene-rate, Hand, Gene-rate
|
89
|
+
|
90
|
+
(('note:★ Extension library(拡張ライブラリー)'))\n
|
91
|
+
(('note:☆ GObject Introspection: Recommended(オススメ)'))
|
92
|
+
|
93
|
+
= Demo\n(('note:デモ'))
|
94
|
+
|
95
|
+
How powerful auto generated bindings\n
|
96
|
+
(('note:自動生成されたバインディングがいかに強力か'))
|
97
|
+
|
98
|
+
= What is ext?\n(('note:拡張ライブラリーってなに?'))
|
99
|
+
|
100
|
+
# RT
|
101
|
+
|
102
|
+
, Ext★, SWIG, FFI, GI☆
|
103
|
+
|
104
|
+
Base\nTech, ((*Ext*)), ((*Ext*)), lib\nffi, lib\nffi
|
105
|
+
Impl.\nby, Hand, Gene-rate, Hand, Gene-rate
|
106
|
+
|
107
|
+
(('note:★ Extension library(拡張ライブラリー)'))\n
|
108
|
+
(('note:☆ GObject Introspection: Recommended(オススメ)'))
|
109
|
+
|
110
|
+
= Extension library\n(('note:拡張ライブラリーとは'))
|
111
|
+
|
112
|
+
* Ruby library written in ((*C*))\n
|
113
|
+
(('note:Cで書かれたRuby用ライブラリー'))
|
114
|
+
* (('wait'))Most bindings are ext lib\n
|
115
|
+
(('note:多くのバインディングは拡張ライブラリーとして実装'))
|
116
|
+
* (({openssl})) is ext lib and bindings\n
|
117
|
+
(('note:(({oepnssl}))は拡張ライブラリーでバインディング'))
|
118
|
+
* Exc.: (({stringio})) is ext lib but...\n
|
119
|
+
(('note:例外:(({stringio}))は拡張ライブラリーだが…'))
|
120
|
+
|
121
|
+
= Ext lib and bindings\n(('note:拡張ライブラリーとバインディング'))
|
122
|
+
|
123
|
+
# image
|
124
|
+
# src = images/extension-library-and-bindings.svg
|
125
|
+
# relative_height = 100
|
126
|
+
|
127
|
+
== slide properties
|
128
|
+
|
129
|
+
: enable-title-on-image
|
130
|
+
false
|
131
|
+
|
132
|
+
= What is libffi?\n(('note:libffiってなに?'))
|
133
|
+
|
134
|
+
# RT
|
135
|
+
|
136
|
+
, Ext★, SWIG, FFI, GI☆
|
137
|
+
|
138
|
+
Base\nTech, Ext, Ext, ((*lib\nffi*)), ((*lib\nffi*))
|
139
|
+
Impl.\nby, Hand, Gene-rate, Hand, Gene-rate
|
140
|
+
|
141
|
+
(('note:★ Extension library(拡張ライブラリー)'))\n
|
142
|
+
(('note:☆ GObject Introspection: Recommended(オススメ)'))
|
143
|
+
|
144
|
+
= libffi and FFI: 1\n(('note:libffiとFFIとは:1'))
|
145
|
+
|
146
|
+
* libffi: Library to impl. FFI
|
147
|
+
* (('wait'))((*F*))oreign ((*F*))unction ((*I*))nterface
|
148
|
+
* Generally:\n
|
149
|
+
All APIs to impl. bindings\n
|
150
|
+
(('note:一般的にはバインディングを実装するためのすべてのAPI'))
|
151
|
+
* Ruby doesn't use "FFI" term\n
|
152
|
+
(('note:Rubyでは「FFI」という単語を使わない'))
|
153
|
+
|
154
|
+
= libffi and FFI: 2\n(('note:libffiとFFIとは:2'))
|
155
|
+
|
156
|
+
* Ruby FFI
|
157
|
+
* (('wait'))Library based on libffi\n
|
158
|
+
(('note:libffiを使ったライブラリー'))
|
159
|
+
* (('wait'))Provides ((*Ruby*)) API\n
|
160
|
+
to implement bindings\n
|
161
|
+
(('note:バインディングを実装するためのRubyレベルのAPIを提供'))
|
162
|
+
|
163
|
+
= libffi and bindings\n(('note:libffiとバインディング'))
|
164
|
+
|
165
|
+
# image
|
166
|
+
# src = images/libffi-and-bindings.svg
|
167
|
+
# relative_height = 100
|
168
|
+
|
169
|
+
== slide properties
|
170
|
+
|
171
|
+
: enable-title-on-image
|
172
|
+
false
|
173
|
+
|
174
|
+
= Impl. language\n(('note:実装言語'))
|
175
|
+
|
176
|
+
# RT
|
177
|
+
|
178
|
+
, Ext★, SWIG, FFI, GI☆
|
179
|
+
|
180
|
+
Base\nTech, Ext, Ext, lib\nffi, lib\nffi
|
181
|
+
Impl.\nlang, C, C+α, Ruby, Ruby
|
182
|
+
|
183
|
+
(('note:★ Extension library(拡張ライブラリー)'))\n
|
184
|
+
(('note:☆ GObject Introspection: Recommended(オススメ)'))
|
185
|
+
|
186
|
+
= Ext impl. by\n(('note:拡張ライブラリーの実装方法'))
|
187
|
+
|
188
|
+
# RT
|
189
|
+
|
190
|
+
, Ext★, SWIG, FFI, GI☆
|
191
|
+
|
192
|
+
Base\nTech, Ext, Ext, lib\nffi, lib\nffi
|
193
|
+
Impl.\nby, ((*Hand*)), ((*Generate*)), Hand, Gene-rate
|
194
|
+
|
195
|
+
(('note:★ Extension library(拡張ライブラリー)'))\n
|
196
|
+
(('note:☆ GObject Introspection: Recommended(オススメ)'))
|
197
|
+
|
198
|
+
= Ext impl. by: Target\n(('note:拡張ライブラリーの実装方法:対象'))
|
199
|
+
|
200
|
+
# coderay c
|
201
|
+
/* hello.h */
|
202
|
+
#pragma once
|
203
|
+
typedef struct hello_t Hello;
|
204
|
+
Hello *hello_new (void);
|
205
|
+
void hello_free (Hello *hello);
|
206
|
+
const char *hello_message(Hello *hello);
|
207
|
+
|
208
|
+
= Ext impl. by hand\n(('note:手動での拡張ライブラリーの実装'))
|
209
|
+
|
210
|
+
(('note:https://github.com/kou/rabbit-slide-kou-rubykaigi-2016/blob/master/c-api/bindings/hello.c'))
|
211
|
+
|
212
|
+
# coderay c
|
213
|
+
#include <ruby.h>
|
214
|
+
|
215
|
+
#include <hello.h>
|
216
|
+
|
217
|
+
static void
|
218
|
+
rb_hello_free(void *data)
|
219
|
+
{
|
220
|
+
Hello *hello = data;
|
221
|
+
hello_free(hello);
|
222
|
+
}
|
223
|
+
|
224
|
+
static const rb_data_type_t rb_hello_type = {
|
225
|
+
"Hello",
|
226
|
+
{
|
227
|
+
NULL,
|
228
|
+
rb_hello_free,
|
229
|
+
NULL,
|
230
|
+
},
|
231
|
+
NULL,
|
232
|
+
NULL,
|
233
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
234
|
+
};
|
235
|
+
|
236
|
+
static VALUE
|
237
|
+
rb_hello_alloc(VALUE klass)
|
238
|
+
{
|
239
|
+
return TypedData_Wrap_Struct(klass, &rb_hello_type, NULL);
|
240
|
+
}
|
241
|
+
|
242
|
+
static VALUE
|
243
|
+
rb_hello_initialize(VALUE self)
|
244
|
+
{
|
245
|
+
Hello *hello;
|
246
|
+
hello = hello_new();
|
247
|
+
DATA_PTR(self) = hello;
|
248
|
+
return Qnil;
|
249
|
+
}
|
250
|
+
|
251
|
+
static VALUE
|
252
|
+
rb_hello_message(VALUE self)
|
253
|
+
{
|
254
|
+
Hello *hello;
|
255
|
+
const char *message;
|
256
|
+
|
257
|
+
TypedData_Get_Struct(self, Hello, &rb_hello_type, hello);
|
258
|
+
message = hello_message(hello);
|
259
|
+
|
260
|
+
return rb_str_new_cstr(message);
|
261
|
+
}
|
262
|
+
|
263
|
+
void
|
264
|
+
Init_hello(void)
|
265
|
+
{
|
266
|
+
VALUE hello;
|
267
|
+
|
268
|
+
hello = rb_define_class("Hello", rb_cData);
|
269
|
+
rb_define_alloc_func(hello, rb_hello_alloc);
|
270
|
+
rb_define_method(hello, "initialize", rb_hello_initialize, 0);
|
271
|
+
rb_define_method(hello, "message", rb_hello_message, 0);
|
272
|
+
}
|
273
|
+
|
274
|
+
= Ext impl. by generation\n(('note:自動生成での拡張ライブラリーの実装'))
|
275
|
+
|
276
|
+
* (('wait'))SWIG can generate impl.\n
|
277
|
+
(('note:Simplified Wrapper and Interface Generator'))\n
|
278
|
+
(('note:SWIGで実装を生成できる'))
|
279
|
+
* (('wait'))An user
|
280
|
+
* TensorFlow: A library for machine intelligence\n
|
281
|
+
(('note:TensorFlow:機械知能のライブラリー'))\n
|
282
|
+
Uses to generate Python bindings\n
|
283
|
+
(('note:Pythonバインディングを生成するために使用'))
|
284
|
+
|
285
|
+
= Ext impl. by SWIG\n(('note:SWIGでの拡張ライブラリーの実装'))
|
286
|
+
|
287
|
+
# coderay c
|
288
|
+
// swig -ruby hello.i -> hello_wrap.c
|
289
|
+
%module hello
|
290
|
+
%{
|
291
|
+
#include <hello.h>
|
292
|
+
%}
|
293
|
+
%include <hello.h>
|
294
|
+
|
295
|
+
= Use ext by SWIG\n(('note:SWIGで作った拡張ライブラリーを使う'))
|
296
|
+
|
297
|
+
irb(main):001:0> require "hello"
|
298
|
+
=> true
|
299
|
+
irb(main):002:0> hello = Hello.hello_new
|
300
|
+
=> #<SWIG::TYPE_p_hello_t:0x000...>
|
301
|
+
irb(main):003:0> Hello.hello_message(hello)
|
302
|
+
=> "Hello"
|
303
|
+
irb(main):004:0> Hello.hello_free(hello)
|
304
|
+
=> nil
|
305
|
+
# Raw C API... :<
|
306
|
+
|
307
|
+
= By SWIG again\n(('note:SWIGでもう一度'))
|
308
|
+
|
309
|
+
# coderay c
|
310
|
+
%module hello
|
311
|
+
%{#include <hello.h>%}
|
312
|
+
typedef struct hello_t {
|
313
|
+
%extend {
|
314
|
+
hello_t() {return hello_new();}
|
315
|
+
~hello_t() {hello_free($self);}
|
316
|
+
const char *message() {return hello_message($self);}
|
317
|
+
}
|
318
|
+
} Hello;
|
319
|
+
|
320
|
+
= Use again\n(('note:もう一度使う'))
|
321
|
+
|
322
|
+
irb(main):001:0> require "hello"
|
323
|
+
=> true
|
324
|
+
irb(main):002:0> hello = Hello::Hello.new
|
325
|
+
=> #<Hello::Hello:0x000...>
|
326
|
+
irb(main):003:0> hello.message
|
327
|
+
=> "Hello"
|
328
|
+
# Object oriented API!
|
329
|
+
|
330
|
+
= Wrap up1: Ext\n(('note:まとめ1:拡張ライブラリー'))
|
331
|
+
|
332
|
+
* (('wait'))By hand: Need many works\n
|
333
|
+
(('note:手動:たくさん書かないといけない'))
|
334
|
+
* (('wait'))By generation: Less works\n
|
335
|
+
(('note:生成:書くことが少ない'))
|
336
|
+
* Need more works for easy to use\n
|
337
|
+
(('note:使いやすいAPIにするにはたくさん書かないといけない'))
|
338
|
+
|
339
|
+
= Wrap up2: Ext\n(('note:まとめ2:拡張ライブラリー'))
|
340
|
+
|
341
|
+
* On maintenance\n
|
342
|
+
e.g.: New functions\n
|
343
|
+
(('note:メンテナンス時:(例:新しい関数が追加された)'))
|
344
|
+
* (('wait'))By hand: Need more works\n
|
345
|
+
(('note:手動:追加作業あり'))
|
346
|
+
* (('wait'))By generation: No more works\n
|
347
|
+
(('note:生成:追加作業なし'))\n
|
348
|
+
This is a large benefit!\n
|
349
|
+
(('note:これは大きな利点!'))
|
350
|
+
|
351
|
+
= libffi impl. by\n(('note:libffiベースでの実装方法'))
|
352
|
+
|
353
|
+
# RT
|
354
|
+
|
355
|
+
, Ext★, SWIG, FFI, GI☆
|
356
|
+
|
357
|
+
Base\nTech, Ext, Ext, lib\nffi, lib\nffi
|
358
|
+
Impl.\nby, Hand, Gene-rate, ((*Hand*)), ((*Generate*))
|
359
|
+
|
360
|
+
(('note:★ Extension library(拡張ライブラリー)'))\n
|
361
|
+
(('note:☆ GObject Introspection: Recommended(オススメ)'))
|
362
|
+
|
363
|
+
= libffi impl. by hand\n(('note:手動でのlibffiベースの実装'))
|
364
|
+
|
365
|
+
# coderay ruby
|
366
|
+
require "ffi"
|
367
|
+
|
368
|
+
module LibHello
|
369
|
+
extend FFI::Library
|
370
|
+
ffi_lib "../../libhello/lib/libhello.so"
|
371
|
+
attach_function :hello_new, [], :pointer
|
372
|
+
attach_function :hello_message, [:pointer], :string
|
373
|
+
attach_function :hello_free, [:pointer], :void
|
374
|
+
end
|
375
|
+
|
376
|
+
= Use libffi impl. by hand\n(('note:手動でのlibffiベースの実装を使う'))
|
377
|
+
|
378
|
+
irb(main):001:0> require "hello"
|
379
|
+
=> true
|
380
|
+
irb(main):002:0> hello = LibHello.hello_new
|
381
|
+
=> #<FFI::Pointer address=0x00000002b07ef0>
|
382
|
+
irb(main):003:0> LibHello.hello_message(hello)
|
383
|
+
=> "Hello"
|
384
|
+
irb(main):004:0> LibHello.hello_free(hello)
|
385
|
+
=> nil
|
386
|
+
# Raw C API... :<
|
387
|
+
|
388
|
+
= Wrap FFI impl. 1\n(('note:FFIでの実装をラップ1'))
|
389
|
+
|
390
|
+
# coderay ruby
|
391
|
+
class Hello
|
392
|
+
def initialize
|
393
|
+
hello = LibHello.hello_new
|
394
|
+
hello_free = LibHello.method(:hello_free)
|
395
|
+
@hello =
|
396
|
+
FFI::AutoPointer.new(hello, hello_free)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
= Wrap FFI impl. 2\n(('note:FFIでの実装をラップ2'))
|
401
|
+
|
402
|
+
# coderay ruby
|
403
|
+
class Hello
|
404
|
+
def message
|
405
|
+
LibHello.hello_message(@hello)
|
406
|
+
endg
|
407
|
+
end
|
408
|
+
|
409
|
+
= Use wrapped impl.\n(('note:ラップした実装を使う'))
|
410
|
+
|
411
|
+
irb(main):001:0> require "hello"
|
412
|
+
=> true
|
413
|
+
irb(main):002:0> hello = Hello.new
|
414
|
+
=> #<Hello:0x000...>
|
415
|
+
irb(main):003:0> hello.message
|
416
|
+
=> "Hello"
|
417
|
+
# Object oriented API!
|
418
|
+
|
419
|
+
= libffi impl. by generation\n(('note:自動生成でのlibffiベースの実装'))
|
420
|
+
|
421
|
+
TODO
|