ffi for rubyists

10,724 views

Published on

introduction to ruby-ffi

ffi for rubyists

  1. 1. RubyistのためのFFI入門 @nanki / 関西闇Ruby会議
  2. 2. 自己紹介
  3. 3. @nanki ■Ruby, JavaScript, Objective-[CJ]...http://blog.netswitch.jp/ - 出町ミスド戦記http://github.com/nankimisdo.rb
  4. 4. misdo.rb
  5. 5. misdo.rb全国のミスタードーナツで毎日開催
  6. 6. misdo.rb全国のミスタードーナツで毎日開催参加費 ドーナツ/コーヒー代(実費)
  7. 7. misdo.rb全国のミスタードーナツで毎日開催参加費 ドーナツ/コーヒー代(実費)Rubyなどを使って自分のことをする
  8. 8. misdo.rb全国のミスタードーナツで毎日開催参加費 ドーナツ/コーヒー代(実費)Rubyなどを使って自分のことをするRuby以外でもOK
  9. 9. misdo.rb全国のミスタードーナツで毎日開催参加費 ドーナツ/コーヒー代(実費)Rubyなどを使って自分のことをするRuby以外でもOKミスドじゃなくてもOK
  10. 10. 本題
  11. 11. RubyがCと向き合う方法
  12. 12. RubyがCと向き合う方法 拡張ライブラリを書く
  13. 13. RubyがCと向き合う方法 拡張ライブラリを書く SWIGを使う
  14. 14. RubyがCと向き合う方法 拡張ライブラリを書く SWIGを使う FFI ☜ NEW!
  15. 15. FFIとは?
  16. 16. libffiForeign Function Interfaceの略呼出規約(Calling Convention)に則って無理矢理呼び出す
  17. 17. func(x1, x2, x3)
  18. 18. func(x1, x2, x3) x3
  19. 19. func(x1, x2, x3) x2 x3
  20. 20. func(x1, x2, x3) x1 x2 x3
  21. 21. func(x1, x2, x3) 戻り先 x1 x2 x3
  22. 22. func(x1, x2, x3) ☞call! 戻り先 x1 x2 x3
  23. 23. func(x1, x2, x3) ♨ x2 x3
  24. 24. func(x1, x2, x3) ♨ x3
  25. 25. func(x1, x2, x3) ♨
  26. 26. func(x1, x2, x3) おわり
  27. 27. ffi(ruby-ffi)
  28. 28.
  29. 29. ffilibffiをRubyから使うためのライブラリ
  30. 30. ffilibffiをRubyから使うためのライブラリhttp://github.com/ffi/ffi
  31. 31. ffilibffiをRubyから使うためのライブラリhttp://github.com/ffi/ffigithubはRubyistだけのものではないのに…
  32. 32. ffilibffiをRubyから使うためのライブラリhttp://github.com/ffi/ffigithubはRubyistだけのものではないのに…我が物顔でffi/ffi
  33. 33. フィッフィ?
  34. 34. フィッフィ入門@nanki / 闇西関Ruby会議
  35. 35. 使い方(1)module LibC extend FFI::Library ffi_lib c # FFI::Library::LIBC # int puts(char*) attach_function :puts, [:string], :intendLibC.puts "Hello!"
  36. 36. 使い方(2) 型: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, ...
  37. 37. 使い方(3) 型 列挙型/構造体/関数ポインタenum :Status, [:Success, 0, :Failure, 1]class Pointer < FFI::Struct layout( :x, :float, :y, :float )endcallback :PaStreamFinishedCallback, [:pointer], :void
  38. 38. 使い方(4) 例 ffi-portaudioより抜粋module PA ffi_lib portaudio enum :PaStreamCallbackResult, [:paContinue, :paComplete, :paAbort] class PaStreamCBTimeInfo < FFI::Struct layout(...) end
  39. 39. 使い方(5) 例 ffi-portaudioより抜粋 callback :PaStreamCallback, [..., PaStreamCBTimeInfo.in, ...], :PaStreamCallbackResult attach_function :Pa_OpenStream, [..., :PaStreamCallback, ...], ...endPA.Pa_OpenStream(..., c = lambda{|...| :paContinue}, ...)
  40. 40. 使い方(5) 例 ffi-portaudioより抜粋 callback :PaStreamCallback, [..., PaStreamCBTimeInfo.in, ...], :PaStreamCallbackResult attach_function :Pa_OpenStream, [..., :PaStreamCallback, ...], ...endPA.Pa_OpenStream(..., c = lambda{|...| :paContinue}, ☜ ...)
  41. 41. 使い方(5) 例 ffi-portaudioより抜粋 callback :PaStreamCallback, [..., PaStreamCBTimeInfo.in, ...], :PaStreamCallbackResult attach_function :Pa_OpenStream, [..., :PaStreamCallback, ...], ...endPA.Pa_OpenStream(..., c = lambda{|...| :paContinue}, ☜ ...) GC対策
  42. 42. なぜフィッフィか
  43. 43. なぜフィッフィか
  44. 44. なぜフィッフィかブリッジコード書きたい?
  45. 45. なぜフィッフィかブリッジコード書きたい?SWIGで生成されたコードで…
  46. 46. なぜフィッフィかブリッジコード書きたい?SWIGで生成されたコードで…レポジトリが汚れない
  47. 47. なぜフィッフィかブリッジコード書きたい?SWIGで生成されたコードで…レポジトリが汚れないCのコードをメンテナンスしなくてよい
  48. 48. なぜフィッフィかブリッジコード書きたい?SWIGで生成されたコードで…レポジトリが汚れないCのコードをメンテナンスしなくてよい(JRuby/Rubiniusなどでも使える)
  49. 49. なぜフィッフィか portaudioの場合拡張ライブラリ N/A SWIG 5350行 フィッフィ 206行
  50. 50. 200行はフィッフィも 結構面倒なのでは?
  51. 51. そこで…
  52. 52. ffi-swig-generator♘ swig -module portaudio -o portaudio.xml -xml portaudio/include/portaudio.h♘ ffi-gen portaudio.xml portaudio.rb
  53. 53. ffi-swig-generator♘ swig -module portaudio -o portaudio.xml -xml portaudio/include/portaudio.h♘ ffi-gen portaudio.xml portaudio.rb SWIG便利
  54. 54. まとめ
  55. 55. まとめ きれなかったものFFI::AutoPointer.new(pointer,self.class.method(:destuctor))ffi-ruby(https://gist.github.com/1336545)Unicodeにはffi(U+FB03)という文字がある
  56. 56. ffi-rubyinclude FFI::Rubyp FFI::Ruby::rb_ary_includes [1, 2], 2# => trueary = rb_ary_newargv = FFI::MemoryPointer.new :pointer, 1argv.write_pointer rb_ary_to_s(ary)rb_io_puts 1, argv, FFI::Ruby.rb_stdout# []
  57. 57. ffi-rubydef 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
  58. 58. ffi-rubydef 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
  59. 59. フィッフィと仲間たち♘ gem dependent ffi | wc -l192 192!
  60. 60. フィッフィと仲間たち ffi-ffi ai Ffrindiau ⓒS4/C http://cyw.s4c.co.uk/en/rhaglenni/ffi-ffi
  61. 61. RubyがC++と向き合う方法
  62. 62.

×