23
2007-11-17 Ruby 拡張モジュール⼊⾨ Ruby 拡張モジュール⼊⾨ むらけん

Ruby 拡張モジュール入門

Embed Size (px)

DESCRIPTION

Ruby の拡張モジュール作成への導入

Citation preview

Page 1: Ruby 拡張モジュール入門

2007-11-17

Ruby拡張モジュール⼊⾨Ruby拡張モジュール⼊⾨むらけん

Page 2: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 1

お し な が きお し な が き拡張モジュールとはなにもしない拡張モジュールhello.so拡張モジュールを作る前にまとめ

Page 3: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6

2

拡張モジュールとは拡張モジュールとは⽇本語でおk

Page 4: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 3

拡張モジュールって何?拡張モジュールって何?

拡張モジュールとは・・・Ruby では実現不可能だけど,C ⾔語なら実現可能な事柄を,C ⾔語で実装して Ruby から使えるようにするための共有ライブラリRuby で実装すると遅いけど,C ⾔語なら実⽤的な実⾏速度を実現できるようなアルゴリズムなどを,C⾔語で実装して Ruby から使えるようにするための共有ライブラリアセンブリ⾔語も使えるよ\(^o^)/

Page 5: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 4

拡張モジュールの例拡張モジュールの例標準添付

Ruby/OpenSSLRuby/Win32APIEnumeratoriconvRuby/TkWin32OLERuby/Zlib

独⽴配布Ruby/GNOME2RubyCocoaLibxml-RubyRuby PostgreSQLMySQL/Rubyfastthreadhttp11 (mongrel)

Page 6: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6

5

なにもしない拡張モジュールなにもしない拡張モジュール

nothing to do

Page 7: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 6

準 備準 備

[nothing.c]voidInit_nothing(void){}

[extconf.rb]require 'mkmf'

create_makefile('nothing')

[depends]nothing.o: nothing.c

3つのファイルを nothing ディレクトリの中に⼊れましょう

~/nothing$ lsdepends extconf.rb nothing.c~/nothing$

Page 8: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 7

コンパイルコンパイルextconf.rb を実⾏することによって Makefile が作られます.作成された Makefile を make することでコンパイルします.make の後に⽣成される nothing.so が拡張モジュールです.

~/nothing$ ruby extconf.rbcreating Makefile~/nothing$ lsMakefile depends extconf.rb nothing.c~/nothing$ makecc -I. -I/usr/lib/ruby/1.8/i486-linux -I/usr/lib/ruby/1.8/i486-linux -I. -fPIC -fno-stric...cc -shared -o nothing.so nothing.o -L"." -L"/usr/lib" -L. -rdynamic -Wl,-export-dynamic ...~/nothing$ lsMakefile depends extconf.rb nothing.c nothing.o nothing.so

Page 9: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 8

使ってみる使ってみる出来上がった nothing.so を Ruby から使うにはrequire 'nothing' を⾏います.

~/nothing$ irbirb(main):001:0> require 'nothing'=> trueirb(main):002:0> exit~/nothing$

Page 10: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 9

ここまでのまとめ (1)ここまでのまとめ (1)

拡張モジュールに必ず必要な関数void Init_モジュール名(void) { ... }拡張モジュールがロードされた直後に Ruby インタプリタがこの関数を呼び出す本来ならば,この関数の中で拡張モジュールの初期化処理が⾏われる

Page 11: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 10

ここまでのまとめ (2)ここまでのまとめ (2)

Ruby に標準添付されている拡張モジュール開発環境

extconf.rb の中で mkmf ライブラリを⽤いて,Makefile を作成するための処理を⾏う•とりあえず

create_makefile('モジュール名')と書くことで「モジュール名.so」を⽣成するためのMakefile が作られる

depends ファイルの中に Makefile に書いて欲しい依存関係を記述する

Page 12: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6

11

hello.sohello.so

そう,こんにちわ

Page 13: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 12

hello.chello.c

[hello.c]#include <ruby.h>#include <stdio.h>

static VALUEhello_hello(VALUE self){VALUE str;

printf("[XXX] hello_hello¥n");

str = rb_str_new2("hello, world");rb_io_puts(1, &str, rb_stdout);

return self;}

[左から続き]voidInit_hello(void){VALUE cHello;

printf("[XXX] Init_hello¥n");

cHello = rb_define_class("Hello", rb_cObject);

rb_define_method(cHello, "hello", hello_hello, 0);

}

Page 14: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 13

コンパイルコンパイル[extconf.rb]require 'mkmf'

create_makefile('hello')

~/hello$ lsdepends extconf.rb hello.c~/hello$ ruby extconf.rbcreating Makefile~/hello$ makecc -I. -I/usr/lib/ruby/1.8/i486-linux -I/usr/lib/ruby/1.8/i486-linux -I. -fPIC -fno-strict-aliasing -g -O2 -fPIC -c hello.ccc -shared -o hello.so hello.o -L"." -L"/usr/lib" -L. -rdynamic -Wl,-export-dynamic -lruby1.8 -lpthread -ldl -lcrypt -lm -lc~/hello$ lsdepends extconf.rb hello.c hello.ohello.so

[depends]hello.o: hello.c $(hdrdir)/ruby.h

Page 15: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 14

~/hello$ irbirb(main):001:0> require 'hello'[XXX] Init_hello=> trueirb(main):002:0> h = Hello.new=> #<Hello:0xb7c7e590>irb(main):003:0> h.hello[XXX] hello_hellohello, world=> #<Hello:0xb7c7e590>irb(main):004:0> exit~/hello$

使ってみる使ってみるvoidInit_hello(void){VALUE cHello;

printf("[XXX] Init_hello¥n");======================================static VALUEhello_hello(VALUE self){VALUE str;

printf("[XXX] hello_hello¥n");~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~return self;

}

Page 16: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 15

ここまでのまとめ (1)ここまでのまとめ (1)

クラスを定義するrb_define_class(クラス名, 親クラスオブジェクト)

クラスにインスタンスメソッドを定義するrb_define_method(

クラスオブジェクト,メソッド名,メソッドを実装している関数,引数の個数)

Page 17: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 16

ここまでのまとめ (2)ここまでのまとめ (2)

メソッドの実体となる関数 (hello_hello)第1仮引数・・・レシーバオブジェクトその他・・・メソッドの引数

Ruby の⽂字列オブジェクトを⽣成するrb_str_new2(C の⽂字列)

putsrb_io_puts(1, &⽂字列, rb_stdout)• 本当は rb_io_puts(argc, argv, rb_stdout) で,argv が puts に渡す実引数の C 配列,argc がその⻑さ

Page 18: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6

17

拡張モジュールを作る前に

拡張モジュールを作る前に

そんなに難しくないよ

Page 19: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 18

おちついて⼀読すべしおちついて⼀読すべしRuby には拡張モジュールの作り⽅のドキュメントがもれなくついてくる!

README.EXTREADME.EXT.ja

.¥" README.EXT.ja - -*- Text -*- created at: Mon Aug 7 16:4

Rubyの拡張ライブラリの作り方を説明します.

1.基礎知識

Cの変数には型があり,データには型がありません.ですから,たとえばポインタをintの変数に代入すると,その値は整数として取り扱われます.逆にRubyの変数には型がなく,データに型があります.この違いのため,CとRubyは相互に変換しなければ,お互いのデータをアクセスできません.

RubyのデータはVALUEというCの型で表現されます.VALUE型のデータはそのデータタイプを自分で知っています.このデータタイプというのはデータ(オブジェクト)の実際の構造を意味していて,Rubyのクラスとはまた違ったものです.

Page 20: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 19

拡張モジュールを作るとはどういうことか?拡張モジュールを作るとはどういうことか?

Ruby インタプリタが理解できることば構⽂⽊C ⾔語

拡張モジュールを作る= Ruby インタプリタとお喋りする

Page 21: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 20

参考になるものたち参考になるものたちRuby のソースを読むべし!

array.chash.cobject.cstring.c

よく使うクラスを実装しているコードを読むことで拡張モジュール作成のための知識を増やそう

Page 22: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6

21

ま と めま と めMA☆TO☆めけーも

Page 23: Ruby 拡張モジュール入門

2007-11-17 Ruby 勉強会@札幌 #6 22

拡張モジュールを作ろう!

C ⾔語で Ruby とお喋りしよう