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.
@@ -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
@@ -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
+
@@ -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で会いましょう。
@@ -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