ffi for rubyists

63
RubyistのためのFFI入門 @nanki / 関西闇Ruby会議

Upload: nanki

Post on 04-Jul-2015

5.457 views

Category:

Technology


4 download

DESCRIPTION

introduction to ruby-ffi

TRANSCRIPT

Page 1: ffi for rubyists

RubyistのためのFFI入門@nanki / 関西闇Ruby会議

Page 2: ffi for rubyists

自己紹介

Page 3: ffi for rubyists

@nanki ■

Ruby, JavaScript, Objective-[CJ]...

http://blog.netswitch.jp/ - 出町ミスド戦記

http://github.com/nanki

misdo.rb

Page 4: ffi for rubyists

misdo.rb

Page 5: ffi for rubyists

misdo.rb

全国のミスタードーナツで毎日開催

Page 6: ffi for rubyists

misdo.rb

全国のミスタードーナツで毎日開催

参加費 ドーナツ/コーヒー代(実費)

Page 7: ffi for rubyists

misdo.rb

全国のミスタードーナツで毎日開催

参加費 ドーナツ/コーヒー代(実費)

Rubyなどを使って自分のことをする

Page 8: ffi for rubyists

misdo.rb

全国のミスタードーナツで毎日開催

参加費 ドーナツ/コーヒー代(実費)

Rubyなどを使って自分のことをする

Ruby以外でもOK

Page 9: ffi for rubyists

misdo.rb

全国のミスタードーナツで毎日開催

参加費 ドーナツ/コーヒー代(実費)

Rubyなどを使って自分のことをする

Ruby以外でもOK

ミスドじゃなくてもOK

Page 10: ffi for rubyists

本題

Page 11: ffi for rubyists

RubyがCと向き合う方法

Page 12: ffi for rubyists

RubyがCと向き合う方法

拡張ライブラリを書く

Page 13: ffi for rubyists

RubyがCと向き合う方法

拡張ライブラリを書く

SWIGを使う

Page 14: ffi for rubyists

RubyがCと向き合う方法

拡張ライブラリを書く

SWIGを使う

FFI ☜ NEW!

Page 15: ffi for rubyists

FFIとは?

Page 16: ffi for rubyists

libffi

Foreign Function Interfaceの略

呼出規約(Calling Convention)に則って

無理矢理呼び出す

Page 17: ffi for rubyists

func(x1, x2, x3)

Page 18: ffi for rubyists

x3

func(x1, x2, x3)

Page 19: ffi for rubyists

x2

x3

func(x1, x2, x3)

Page 20: ffi for rubyists

x1

x2

x3

func(x1, x2, x3)

Page 21: ffi for rubyists

戻り先

x1

x2

x3

func(x1, x2, x3)

Page 22: ffi for rubyists

戻り先

x1

x2

x3

☞call!

func(x1, x2, x3)

Page 23: ffi for rubyists

x2

x3

func(x1, x2, x3)

Page 24: ffi for rubyists

x3

func(x1, x2, x3)

Page 25: ffi for rubyists

func(x1, x2, x3)

Page 26: ffi for rubyists

func(x1, x2, x3)

おわり

Page 27: ffi for rubyists

ffi(ruby-ffi)

Page 28: ffi for rubyists

ffi

Page 29: ffi for rubyists

libffiをRubyから使うためのライブラリ

ffi

Page 30: ffi for rubyists

libffiをRubyから使うためのライブラリ

http://github.com/ffi/ffi

ffi

Page 31: ffi for rubyists

libffiをRubyから使うためのライブラリ

http://github.com/ffi/ffi

githubはRubyistだけのものではないのに…

ffi

Page 32: ffi for rubyists

libffiをRubyから使うためのライブラリ

http://github.com/ffi/ffi

githubはRubyistだけのものではないのに…

我が物顔でffi/ffi

ffi

Page 33: ffi for rubyists
Page 34: ffi for rubyists

フィッフィ?

Page 35: ffi for rubyists

フィッフィ入門@nanki / 闇西関Ruby会議

Page 36: ffi for rubyists

module LibC extend FFI::Library

ffi_lib 'c' # FFI::Library::LIBC

# int puts(char*) attach_function :puts, [:string], :intend

LibC.puts "Hello!"

使い方(1)

Page 37: ffi for rubyists

:short # 16bit int :int # 32bit int :long_long # 64bit int :long # long

:float # float :double # double :string # NULL-terminated :pointer # pointer

:void, :float, :double, :varargs, ...

使い方(2) 型

Page 38: ffi for rubyists

enum :Status, [:Success, 0, :Failure, 1]

class Pointer < FFI::Struct layout( :x, :float, :y, :float )end

callback :PaStreamFinishedCallback, [:pointer], :void

使い方(3) 型列挙型/構造体/関数ポインタ

Page 39: ffi for rubyists

module PA ffi_lib 'portaudio'

enum :PaStreamCallbackResult, [:paContinue, :paComplete, :paAbort]

class PaStreamCBTimeInfo < FFI::Struct layout(...) end

使い方(4) 例ffi-portaudioより抜粋

Page 40: ffi for rubyists

callback :PaStreamCallback, [..., PaStreamCBTimeInfo.in, ...], :PaStreamCallbackResult

attach_function :Pa_OpenStream, [..., :PaStreamCallback, ...], ...end

PA.Pa_OpenStream(..., c = lambda{|...| :paContinue}, ...)

使い方(5) 例ffi-portaudioより抜粋

Page 41: ffi for rubyists

callback :PaStreamCallback, [..., PaStreamCBTimeInfo.in, ...], :PaStreamCallbackResult

attach_function :Pa_OpenStream, [..., :PaStreamCallback, ...], ...end

PA.Pa_OpenStream(..., c = lambda{|...| :paContinue}, ...)

使い方(5) 例

ffi-portaudioより抜粋

Page 42: ffi for rubyists

callback :PaStreamCallback, [..., PaStreamCBTimeInfo.in, ...], :PaStreamCallbackResult

attach_function :Pa_OpenStream, [..., :PaStreamCallback, ...], ...end

PA.Pa_OpenStream(..., c = lambda{|...| :paContinue}, ...)

使い方(5) 例

☜GC対策

ffi-portaudioより抜粋

Page 43: ffi for rubyists

なぜフィッフィか

Page 44: ffi for rubyists

なぜフィッフィか

Page 45: ffi for rubyists

なぜフィッフィか

ブリッジコード書きたい?

Page 46: ffi for rubyists

なぜフィッフィか

ブリッジコード書きたい?

SWIGで生成されたコードで…

Page 47: ffi for rubyists

なぜフィッフィか

ブリッジコード書きたい?

SWIGで生成されたコードで…

レポジトリが汚れない

Page 48: ffi for rubyists

なぜフィッフィか

ブリッジコード書きたい?

SWIGで生成されたコードで…

レポジトリが汚れない

Cのコードをメンテナンスしなくてよい

Page 49: ffi for rubyists

なぜフィッフィか

ブリッジコード書きたい?

SWIGで生成されたコードで…

レポジトリが汚れない

Cのコードをメンテナンスしなくてよい

(JRuby/Rubiniusなどでも使える)

Page 50: ffi for rubyists

拡張ライブラリ N/A

SWIG 5350行

フィッフィ 206行

なぜフィッフィかportaudioの場合

Page 51: ffi for rubyists

200行はフィッフィも結構面倒なのでは?

Page 52: ffi for rubyists

そこで…

Page 53: ffi for rubyists

♘ swig -module portaudio -o portaudio.xml -xml portaudio/include/portaudio.h

♘ ffi-gen portaudio.xml portaudio.rb

ffi-swig-generator

Page 54: ffi for rubyists

♘ swig -module portaudio -o portaudio.xml -xml portaudio/include/portaudio.h

♘ ffi-gen portaudio.xml portaudio.rb

ffi-swig-generator

SWIG便利

Page 55: ffi for rubyists

まとめ

Page 56: ffi for rubyists

まとめきれなかったもの

FFI::AutoPointer.new(pointer, self.class.method(:destuctor))

ffi-ruby(https://gist.github.com/1336545)

Unicodeにはffi(U+FB03)という文字がある

Page 57: ffi for rubyists

include FFI::Ruby

p FFI::Ruby::rb_ary_includes [1, 2], 2# => true

ary = rb_ary_newargv = FFI::MemoryPointer.new :pointer, 1argv.write_pointer rb_ary_to_s(ary)rb_io_puts 1, argv, FFI::Ruby.rb_stdout

# []

ffi-ruby

Page 58: ffi for rubyists

def from_native(value, ctx=nil) id = if value.address & 0x0f == 0xe value.address >> 8 else rb_num2long rb_obj_id value end ObjectSpace._id2ref idend

ffi-ruby

Page 59: ffi for rubyists

def to_native(obj, ctx=nil) id = obj.__id__ case obj when Symbol FFI::Pointer.new id << 8 | 0xe when Fixnum, FalseClass, TrueClass, NilClass FFI::Pointer.new id else FFI::Pointer.new id << 1 endend

ffi-ruby

Page 60: ffi for rubyists

♘ gem dependent ffi | wc -l192

フィッフィと仲間たち

192!

Page 61: ffi for rubyists

フィッフィと仲間たち

ⓒS4/C

http://cyw.s4c.co.uk/en/rhaglenni/ffi-ffi

ffi-ffi a'i Ffrindiau

Page 62: ffi for rubyists

RubyがC++と向き合う方法

Page 63: ffi for rubyists