lispとrubyとpythonと その4 Cライブラリの呼び出し(ruby)
つぎはruby。
rubyだとCライブラリを呼び出すというよりはrubyのクラスをCで書く感じ。
ruby1.9でためしたんだけど、1.9では
RSTRING(xxx).ptr
とか
RSTRING(xxx).len
ではなくて
RSTRING_LEN(xxx)
RSTRING_PTR(xxx)
と書くみたい。
参考はこのへん。
http://i.loveruby.net/w/RubyExtensionProgrammingGuide.html
http://wiki.livedoor.jp/aqualung/d/Ruby%a4%ce%b3%c8%c4%a5%a5%e9%a5%a4%a5%d6%a5%e9%a5%ea%a4%ce%ba%ee%a4%ea%ca%fd#content_1_5_1
でcで書いた拡張ライブラリがこんなの。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ruby.h> typedef struct { VALUE prefix; VALUE suffix; } decorator; void decorator_mark(decorator *p) { rb_gc_mark(p->prefix); rb_gc_mark(p->suffix); } void decorator_free(decorator *p) { } VALUE decorator_alloc(VALUE cls) { decorator *p = ALLOC(decorator); return Data_Wrap_Struct(cls,decorator_mark,decorator_free,p); } VALUE decorator_initialize(VALUE self,VALUE prefix,VALUE suffix) { decorator *p; Data_Get_Struct(self, decorator, p); Check_Type(prefix,T_STRING); Check_Type(suffix,T_STRING); p->prefix = prefix; p->suffix = suffix; return Qnil; } VALUE decorator_get_string(VALUE self,VALUE str) { Check_Type(str,T_STRING); decorator *p; Data_Get_Struct(self, decorator, p); char* buf = ALLOC_N(char,RSTRING_LEN(p->prefix) + RSTRING_LEN(str) + RSTRING_LEN(p->suffix) + 1); memset(buf,0,RSTRING_LEN(p->prefix) + RSTRING_LEN(str) + RSTRING_LEN(p->suffix) + 1); strncat(buf,RSTRING_PTR(p->prefix),RSTRING_LEN(p->prefix)); strncat(buf,RSTRING_PTR(str),RSTRING_LEN(str)); strncat(buf,RSTRING_PTR(p->suffix),RSTRING_LEN(p->suffix)); return rb_str_new2(buf); } void Init_decorator() { VALUE d; d = rb_define_class("Decorator", rb_cObject); rb_define_alloc_func(d, decorator_alloc); rb_define_private_method(d, "initialize", decorator_initialize, 2); rb_define_method(d, "get_string", decorator_get_string, 1); }
で、こんな感じのスクリプトを実行
ruby -r mkmf -e 'create_makefile("decorator")' make # ruby
実行するとmakeまで走ってdecorator.soができる。
rubyからの呼び出しはこんな感じ。
require 'decorator.so' d = Decorator.new "start:" , ":end" puts d.get_string("aaa")