続き.
##数値のやりとり 整数の加算をやってみる.
###処理実体
- add.c
int add(a, b)
int a, b;
{
return(a + b);
}
int を 2 つ受け取って加算した結果を int で返す.コードに問題ないかをちょっとテストのために実行してみる
- main.c
#include <stdio.h>
int add(int a, int b);
int main()
{
int a, b;
a = 1;
b = 2;
printf("%d + %d = %d\n", a, b, add(a, b));
}
% cc -o add add.c main.c
% ./add
1 + 2 = 3
まあ普通に実行される.
###C と Ruby の接続 Ruby では数値ですらオブジェクトなので, C の int 型に変換する必要がある.それをやってくれるのが,以下のマクロ・関数らしい. :FIX2INT:Ruby オブジェクトを int 型へ変換する :NUM2INT:Numeric かどうかをチェックしてから int 型へと変換する.Numeric でない場合は例外を吐く. :INT2FIX:signed int(31bit) を Ruby の Fixnum へと変換する. :INT2NUM:int を Ruby の Interger へ変換する.桁あふれの場合は Bignum へと自動拡張して変換する. :NUM2DBL:Numeric かどうかをチェックしてから double 型へと変換する.Numeric でない場合は例外を吐く. :rb_float_new(float):float/double 型の実数を Float 型へと変換する.
そしてこれを使ってラッパーを作る.
- test2.c
#include "ruby.h"
int add(int a, int b);
VALUE wrap_add(self, aa, bb)
VALUE self, aa, bb;
{
int a, b, result;
a = FIX2INT(aa); // FIX2INT によって,VALUE 型構造体を int 型へ変換する
b = FIX2INT(bb); // 同上
result = add(a, b);
return INT2FIX(result); // INT2FIX によって,int 型を VALUE 型構造体へ変換する
}
void Init_test()
{
VALUE module;
module = rb_define_module("Test"); // Test モジュールを生成する
rb_define_module_function(module, "add", wrap_add, 2); // module(Test モジュール) に add メソッドを,引数の数を2として登録する
}
###処理の流れ 基本的に前回と一緒.ことなるのは上記のマクロ使って C の型と Ruby オブジェクトを相互変換していること.
###コンパイルして実行する extconf.rb は前回と同じのを使う.
- extconf.rb
require 'mkmf'
create_makefile('test')
% ruby extconf.rb
% make
% ruby -r'test' -e'puts Test.add(1,2)'
3
Ruby オブジェクトと C の型の相互変換用のマクロなり関数なりがあるので,それを使えば接続にはそれほど苦労しない印象.
comments powered by Disqus