ffi for rubyists

Post on 04-Jul-2015

5.459 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

introduction to ruby-ffi

TRANSCRIPT

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

自己紹介

@nanki ■

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

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

http://github.com/nanki

misdo.rb

misdo.rb

misdo.rb

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

misdo.rb

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

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

misdo.rb

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

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

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

misdo.rb

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

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

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

Ruby以外でもOK

misdo.rb

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

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

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

Ruby以外でもOK

ミスドじゃなくてもOK

本題

RubyがCと向き合う方法

RubyがCと向き合う方法

拡張ライブラリを書く

RubyがCと向き合う方法

拡張ライブラリを書く

SWIGを使う

RubyがCと向き合う方法

拡張ライブラリを書く

SWIGを使う

FFI ☜ NEW!

FFIとは?

libffi

Foreign Function Interfaceの略

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

無理矢理呼び出す

func(x1, x2, x3)

x3

func(x1, x2, x3)

x2

x3

func(x1, x2, x3)

x1

x2

x3

func(x1, x2, x3)

戻り先

x1

x2

x3

func(x1, x2, x3)

戻り先

x1

x2

x3

☞call!

func(x1, x2, x3)

x2

x3

func(x1, x2, x3)

x3

func(x1, x2, x3)

func(x1, x2, x3)

func(x1, x2, x3)

おわり

ffi(ruby-ffi)

ffi

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

ffi

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

http://github.com/ffi/ffi

ffi

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

http://github.com/ffi/ffi

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

ffi

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

http://github.com/ffi/ffi

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

我が物顔でffi/ffi

ffi

フィッフィ?

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

module LibC extend FFI::Library

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

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

LibC.puts "Hello!"

使い方(1)

: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) 型

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

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

callback :PaStreamFinishedCallback, [:pointer], :void

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

module PA ffi_lib 'portaudio'

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

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

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

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

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

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

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

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

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

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

使い方(5) 例

ffi-portaudioより抜粋

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

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

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

使い方(5) 例

☜GC対策

ffi-portaudioより抜粋

なぜフィッフィか

なぜフィッフィか

なぜフィッフィか

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

なぜフィッフィか

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

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

なぜフィッフィか

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

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

レポジトリが汚れない

なぜフィッフィか

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

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

レポジトリが汚れない

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

なぜフィッフィか

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

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

レポジトリが汚れない

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

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

拡張ライブラリ N/A

SWIG 5350行

フィッフィ 206行

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

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

そこで…

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

♘ ffi-gen portaudio.xml portaudio.rb

ffi-swig-generator

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

♘ ffi-gen portaudio.xml portaudio.rb

ffi-swig-generator

SWIG便利

まとめ

まとめきれなかったもの

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

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

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

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

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

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

♘ gem dependent ffi | wc -l192

フィッフィと仲間たち

192!

フィッフィと仲間たち

ⓒS4/C

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

ffi-ffi a'i Ffrindiau

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

top related