Ads by Google
新しい記事を書く事で広告が消せます。
私は知識に何ものかを付け加え,また他の人々がより多くのものを付け加える手助けをした --- G.H.ハーディ
#include<ruby.h>
#include<gauche.h>
/* 参考 : http://i.loveruby.net/w/RubyExtensionProgrammingGuide.html */
struct gaucheObj {
ScmObj env;
};
static VALUE scmobj_alloc(VALUE klass) {
struct gaucheObj *o = ALLOC(struct gaucheObj);
return Data_Wrap_Struct(klass, 0, -1, o);
}
static VALUE scmobj_initialize(VALUE self) {
struct gaucheObj *o;
Data_Get_Struct(self, struct gaucheObj, o);
o->env = Scm_MakeModule(NULL, FALSE);
return Qnil;
}
VALUE gauche_eval(VALUE self, VALUE s){
char *msg, *code = STR2CSTR(s);
struct gaucheObj *o;
ScmObj result, error;
/* 出力文字列ポート開く */
ScmObj os = Scm_MakeOutputStringPort(TRUE);
Data_Get_Struct(self, struct gaucheObj, o);
/* Scheme レベルでエラーハンドリング */
/* http://alohakun.blog7.fc2.com/blog-entry-517.html */
/* 0.8.8 以降では,もっとちゃんとしたやり方があります (古いやり方) */
Scm_Define(SCM_MODULE(o->env), SCM_SYMBOL(SCM_INTERN("*input*")), SCM_MAKE_STR_COPYING(code));
Scm_Define(SCM_MODULE(o->env), SCM_SYMBOL(SCM_INTERN("*error*")), SCM_FALSE);
result = Scm_EvalCString("(guard (e (else (set! *error* e) #f)) (eval (read-from-string *input*) (current-module)))", SCM_OBJ(o->env));
error = Scm_GlobalVariableRef(SCM_MODULE(o->env), SCM_SYMBOL(SCM_INTERN("*error*")), 0);
/* 文字列を評価した結果をポートに書き込む */
if (!SCM_FALSEP(error))
Scm_Write(error, os, SCM_WRITE_DISPLAY);
else
Scm_Write(result, os, SCM_WRITE_DISPLAY);
msg = Scm_GetString(SCM_STRING(Scm_GetOutputString(SCM_PORT(os))));
/* ポート閉じる */
Scm_ClosePort(SCM_PORT(os));
return rb_str_new2(msg);
}
void Init_Gauche(void){
VALUE Gauche;
GC_INIT(); Scm_Init(GAUCHE_SIGNATURE);
Gauche = rb_define_class("Gauche", rb_cObject);
rb_define_alloc_func(Gauche, scmobj_alloc);
rb_define_private_method(Gauche, "initialize", scmobj_initialize, 0);
rb_define_method(Gauche, "eval", gauche_eval, 1);
}
require "mkmf"
dir_config('gauche')
have_header('gauche.h')
have_library('gauche')
have_library('dl')
have_library('crypt')
have_library('util')
have_library('pthread')
create_makefile('Gauche')
$ ls
extconf.rb extgauche.c
$ ruby extconf.rb --with-gauche-include=/usr/lib/gauche/0.8.7/include --with-gauche-lib=/usr/lib/gauche/0.8.7/i486-pc-linux-gnu
checking for gauche.h... yes
checking for main() in -lgauche... yes
checking for main() in -ldl... yes
checking for main() in -lcrypt... yes
checking for main() in -lutil... yes
checking for main() in -lpthread... yes
creating Makefile
$ make
gcc -I. -I. -I/usr/lib/ruby/1.8/i486-linux -I. -DHAVE_GAUCHE_H -I/usr/lib/gauche/0.8.7/include -fPIC -Wall -g -fno-strict-aliasing -O2 -fPIC -c extgauche.c
In file included from /usr/lib/gauche/0.8.7/include/gauche.h:48,
from extgauche.c:9:
/usr/lib/gauche/0.8.7/include/gauche/config.h:280:1: warning: "SIZEOF_OFF_T" redefined
In file included from /usr/lib/ruby/1.8/i486-linux/ruby.h:24,
from extgauche.c:8:
/usr/lib/ruby/1.8/i486-linux/config.h:25:1: warning: this is the location of the previous definition
gcc -shared -rdynamic -Wl,-export-dynamic -L"/usr/lib/gauche/0.8.7/i486-pc-linux-gnu" -L"/usr/lib" -o Gauche.so extgauche.o -lruby1.8 -lpthread -lutil -lcrypt -ldl -lgauche -lpthread -ldl -lcrypt -lm -lc
$ cat test.rb
require "Gauche.so"
g = Gauche.new
s = g.eval("(+ 1 2)")
print s,"\n"
$ ls
Gauche.so Makefile extconf.rb extgauche.c extgauche.o mkmf.log test.rb
$ ruby test.rb
3