スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
新しい記事を書く事で広告が消せます。
【Ruby】Ruby拡張モジュールの開発
新年だいぶあけましておめでとうございます。
僕は年末に腰を痛めてしまい、新年早々大変なお正月でした。
厄年の最後に凄いのが来たか。。という感じです。
今日は前から少し気になっていた「rubyの拡張」について少し書いてみたいと思います。
早速コードから
first_test.c

extconf.rb
require 'mkmf'
create_makefile("first_test");
同じディレクトリ内にこの2つのファイルを用意しておけば大丈夫です。
extconf.rbはMakefileを作るためのスクリプトになります。
そしてextensionのソースの方ですが
やりたい事としては
1. Arrayオブジェクトのインスタンス変数@listをもつ
2. インスタンス変数@listに対してなにがしかのオブジェクトを追加するaddItemメソッドをもつ
3. もちろんコンストラクタであるinitializeメソッドをもつ
そんな機能をもつFirstTestクラスの開発をしているソースコードになります
ここまでで大体はイメージがつけられると思います。
何よりもよく出現しているVALUEというものがあります
Rubyはすべてのものがオブジェクトであり、変数と呼ばれるものはすべてオブジェクトへのリファレンスになります。C言語から見た場合、これらのリファレンスはポインタというもので表現ができます。このオブジェクトのデータやメソッドなどの詳細情報が格納されたメモリ領域を指すポインタがVALUE型の変数として参照されます。
つまりC言語からRubyのオブジェクトを受け渡しするにはこのVALUE型の値を受け渡しすることになります。
次に関数などのAPIについてですが細かいAPIの仕様については調べていただくとして
ここではざっくりと主要なAPIをササッとピックアップしたいと思います。
1. rb_funcall(VALUE recv, ID id, int argc, ...)
オブジェクトrecvのidで特定されるメソッドを呼び出す。
(IDはメソッドを管理するために内部に設けられたシンボルテーブルの管理用のID)
argcはメソッドの引数、あとに(あれば)引数自体が入ります。
今回の例では
Arrayクラスのインスタンスであるlistというオブジェクトのid_push(後述)で識別されるメソッドを引数1つobjを指定して呼び出す。
という呼び出しかたをしています。
2. rb_intern(char *name)
nameというメソッドのIDを取得する
今回の例では"push"というメソッドのIDを取得しています。
(ArrayクラスやHashクラスにあるpushメソッドのことです)
Arrayクラスのインスタンスである@listのpushメソッドを今回開発しているaddItemメソッド内で呼び出すことを上の2つのC言語の関数で実現する訳ですね。
def addItem(item)
@list.push(item)
end
Rubyで書くとこのようなことですね。
いよいよビルドしてみます。
ここまで準備できればもう簡単です
先ほど用意したextconf.rbを実行するだけでMakefileが完成します
1. Makefileの作成
ruby extconf.rb
2. makeの実行
make
3. 動作確認
makeが終わると*.soなどのオブジェクトファイルができていると思います。
今回の例ではfirst_test.soが作成されていると思います。
そこでこんなスクリプトを書いて動作の確認をしてみたいと思います。
1 require 'first_test'
2
3 o = FirstTest.new
4
5 o.addItem(1);
6 o.addItem(2);
7 o.addItem('hoge');
8
9 p o
このスクリプトを実行すると
#<FirstTest:0xb804c834 @list=[1, 2, "hoge"]>
こんな結果が得られ、今回の@listというインスタンス変数にaddItemを追加するという目的が達成されていることが確認できます。
以上初めての「Ruby拡張モジュールの開発」でした。
最後に大変ご挨拶遅くなりましたが、今年もどうぞよろしくお願い致します。
僕は年末に腰を痛めてしまい、新年早々大変なお正月でした。
厄年の最後に凄いのが来たか。。という感じです。
今日は前から少し気になっていた「rubyの拡張」について少し書いてみたいと思います。
早速コードから
first_test.c

extconf.rb
require 'mkmf'
create_makefile("first_test");
同じディレクトリ内にこの2つのファイルを用意しておけば大丈夫です。
extconf.rbはMakefileを作るためのスクリプトになります。
そしてextensionのソースの方ですが
やりたい事としては
1. Arrayオブジェクトのインスタンス変数@listをもつ
2. インスタンス変数@listに対してなにがしかのオブジェクトを追加するaddItemメソッドをもつ
3. もちろんコンストラクタであるinitializeメソッドをもつ
そんな機能をもつFirstTestクラスの開発をしているソースコードになります
ここまでで大体はイメージがつけられると思います。
何よりもよく出現しているVALUEというものがあります
Rubyはすべてのものがオブジェクトであり、変数と呼ばれるものはすべてオブジェクトへのリファレンスになります。C言語から見た場合、これらのリファレンスはポインタというもので表現ができます。このオブジェクトのデータやメソッドなどの詳細情報が格納されたメモリ領域を指すポインタがVALUE型の変数として参照されます。
つまりC言語からRubyのオブジェクトを受け渡しするにはこのVALUE型の値を受け渡しすることになります。
次に関数などのAPIについてですが細かいAPIの仕様については調べていただくとして
ここではざっくりと主要なAPIをササッとピックアップしたいと思います。
1. rb_funcall(VALUE recv, ID id, int argc, ...)
オブジェクトrecvのidで特定されるメソッドを呼び出す。
(IDはメソッドを管理するために内部に設けられたシンボルテーブルの管理用のID)
argcはメソッドの引数、あとに(あれば)引数自体が入ります。
今回の例では
Arrayクラスのインスタンスであるlistというオブジェクトのid_push(後述)で識別されるメソッドを引数1つobjを指定して呼び出す。
という呼び出しかたをしています。
2. rb_intern(char *name)
nameというメソッドのIDを取得する
今回の例では"push"というメソッドのIDを取得しています。
(ArrayクラスやHashクラスにあるpushメソッドのことです)
Arrayクラスのインスタンスである@listのpushメソッドを今回開発しているaddItemメソッド内で呼び出すことを上の2つのC言語の関数で実現する訳ですね。
def addItem(item)
@list.push(item)
end
Rubyで書くとこのようなことですね。
いよいよビルドしてみます。
ここまで準備できればもう簡単です
先ほど用意したextconf.rbを実行するだけでMakefileが完成します
1. Makefileの作成
ruby extconf.rb
2. makeの実行
make
3. 動作確認
makeが終わると*.soなどのオブジェクトファイルができていると思います。
今回の例ではfirst_test.soが作成されていると思います。
そこでこんなスクリプトを書いて動作の確認をしてみたいと思います。
1 require 'first_test'
2
3 o = FirstTest.new
4
5 o.addItem(1);
6 o.addItem(2);
7 o.addItem('hoge');
8
9 p o
このスクリプトを実行すると
#<FirstTest:0xb804c834 @list=[1, 2, "hoge"]>
こんな結果が得られ、今回の@listというインスタンス変数にaddItemを追加するという目的が達成されていることが確認できます。
以上初めての「Ruby拡張モジュールの開発」でした。
最後に大変ご挨拶遅くなりましたが、今年もどうぞよろしくお願い致します。
スポンサーサイト
Comment