Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rubyの拡張をCrystalで書いてみる

 Rubyの拡張をCrystalで書いてみる

Tokyo Crystal Meetup #3 (2016-01-22)

Hirofumi Wakasugi

January 22, 2016
Tweet

More Decks by Hirofumi Wakasugi

Other Decks in Programming

Transcript

  1. /BUJWF&YUFOTJPO Fetching: nokogiri-1.6.7.1.gem (100%) Building native extensions. This could take

    a while... w ಛʹ࣮ߦ଎౓͕ॏཁͳॲཧΛ$Ͱॻ͘͜ͱ͕Ͱ͖Δ w طଘͷ$ϥΠϒϥϦΛར༻͢Δ͜ͱ͕Ͱ͖Δ 3VCZ͸$ݴޠͰ֦ுϥΠϒϥϦΛॻ͘͜ͱ͕Ͱ͖Δ
  2. $SZTUBM$-JCSBSZ#JOEJOHT lib LibC fun pow(x: Float64, y: Float64) : Float64

    fun sqrt(val: Float64) : Float64 end puts(LibC.pow(10, 10)) puts(LibC.sqrt(4)) end $SZTUBMͰ$ͷόΠϯσΟϯάΛॻ͘ͷ͸ͱͯ΋؆୯
  3. def fibonacci(n) return n if n <= 1 fibonacci(n -

    1) + fibonacci(n - 2) end ·ͣɺ͜ͷ୯७ͳϑΟϘφον਺ྻͷؔ਺Λ 3VCZ֦ுϥΠϒϥϦͱͯ͠$SZTUBMͰॻ͖·͢ &YBNQMF
  4. lib LibRuby type VALUE = Void* $rb_cObject : VALUE fun

    rb_define_global_function(name : UInt8*, func : VALUE, VALUE -> VALUE, argc : Int32) fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE end def fibonacci_cr(self : LibRuby::VALUE, value : LibRuby::VALUE) int_value = LibRuby.rb_num2int(value) LibRuby.rb_int2inum(fibonacci_cr2(int_value)) end def fibonacci_cr2(n) return n if n <= 1 fibonacci_cr2(n - 1) + fibonacci_cr2(n - 2) end fun init = Init_extension_with_crystal GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) LibRuby.rb_define_global_function("fibonacci_cr", ->fibonacci_cr, 1); end &YBNQMFpCPCBDDJ@DS
  5. user system total real fibonacci (ruby) 16.760000 0.040000 16.800000 (

    16.963310) fibonacci (crystal) 0.830000 0.010000 0.840000 ( 0.827128) ͏Μɺ଎͍ &YBNQMF
  6. class Takeuchi def self.tarai(x, y, z) if y < x

    tarai( tarai(x - 1, y, z), tarai(y - 1, z, x), tarai(z - 1, x, y) ) else y end end end ͨΒ͍ճؔ͠਺΋ॻ͍ͯΈ·͢ &YBNQMF
  7. lib LibRuby type VALUE = Void* $rb_cObject : VALUE fun

    rb_define_class(name : UInt8*, super : VALUE) : VALUE fun rb_define_module_function(klass : VALUE, name : UInt8*, func : VALUE, VALUE, VALUE, VALUE -> VALUE, argc : Int32) fun rb_num2int(value : VALUE) : Int32 fun rb_int2inum(value : Int32) : VALUE end def tarai(self : LibRuby::VALUE, x : LibRuby::VALUE, y : LibRuby::VALUE, z : LibRuby::VALUE) int_x = LibRuby.rb_num2int(x) int_y = LibRuby.rb_num2int(y) int_z = LibRuby.rb_num2int(z) LibRuby.rb_int2inum(tarai2(int_x, int_y, int_z)) end def tarai2(x, y, z) if y < x tarai2( tarai2(x - 1, y, z), tarai2(y - 1, z, x), tarai2(z - 1, x, y) ) else y end end fun init = Init_extension_with_crystal GC.init LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) rb_class_takeuchi = LibRuby.rb_define_class("TakeuchiCr", LibRuby.rb_cObject) LibRuby.rb_define_module_function(rb_class_takeuchi, "tarai", ->tarai, 3); end &YBNQMF5BLFVDIJ$SUBSBJ
  8. user system total real tarai (ruby) 19.810000 0.050000 19.860000 (

    20.248620) tarai (crystal) 0.970000 0.000000 0.970000 ( 0.998764) ͏Μɺ଎͍ &YBNQMF
  9. 5TVSBNJ person = LibRuby.rb_define_class("Person", LibRuby.rb_cObject) LibRuby.rb_define_method(person, "Hello", ->hello, 1); w

    $SZTUBMͷදݱྗΛ׆༻͢Δ͜ͱ͕೉͍͠ w ن໛͕େ͖͘ͳͬͯ͘Δͱ͔ͳΓݟ௨͕͠ѱ͘ͳΔ ݁ہɺී௨ʹ࢖͏ͱ$"1*ͷόΠϯσΟϯάͰ͔͠ͳ͍
  10. 5TVSBNJ fun rb_define_method(klass : VALUE, name : UInt8*, func :

    VALUE, VALUE -> VALUE, argc : Int32) w ؔ਺ͷܕΛࢦఆ͢Δඞཁ͕͋Δ w ͜ΕҎ֎ͷܕͷؔ਺Λ౉͢ͱίϯύΠϧΤϥʔ 3VCZ$"1*ؔ਺ͷҾ਺͕ؔ਺ϙΠϯλͷͱ͖ʜ
  11. 1SPPGPG$PODFQU 1P$ ruby_extension "test_ruby", class Foo def foo(a) "From Crystal!!

    #{a}" end end SVCZ@FYUFOTJPOϚΫϩͰίʔυ จࣈྻ Λॲཧ ϚΫϩʹ౉͞Εͨίʔυ͸1BSTFSͰύʔε͞ΕΔ
  12. 1SPPGPG$PODFQU 1P$ class MyVisitor < Visitor … def visit(node :

    ClassDef) @str << %(_class = Ruby::Class.new "#{node.name}"\n) end def visit(node : Def) @str << %(_class.def "#{node.name}", #{node.args.size}, ) @str << %[->(self : LibRuby::VALUE, ] node.args.each do |arg| @str << %(_#{arg.name} : LibRuby::VALUE, ) … end … end "45ϊʔυ͸7JTJUPSΛܧঝͨ͠ΫϥεͰॲཧ͞ΕΔ ؔ਺ϙΠϯλ͸ܕΛ7PJE Ͱఆ͓͍ٛͯͯ͠ɺ͜͜Ͱ۩ମతͳܕͱͯ͠ઃఆ͞ΕΔ