From: Masaaki A. <mas...@gm...> - 2011-12-18 05:11:01
|
青柳です。 > あぁ、そうではなく、単にスタック上にVALUEが置いてあればGCの > ときにスタック上のVALUEをmarkしてくれるから大丈夫なんです。 なるほど、根本的に理解していませんでした。。。 RB_GC_GUARDの辺りやスタック上に残り易くなる云々は、まだよく分かっていませんが いつか勉強しようと思います。 >> if (SYMBOL_P(*value)) { >> str = rb_String(*value); > > 文字列への変換はStringValue()を使ったほうがいいです。 これは、シンボルがto_strを持っていないため、rb_Stringを使用しました。 > こんな感じでvalueの他にバッファ用のVALUEも別途受け取ってstr > の代わりに使うように大丈夫そうな気がしますが、それだと使いづ > らいですよねぇ。 > http://d.hatena.ne.jp/nagachika/20111011/ruby_extension_library_howto_tmp_buffer > > あとは、const gchar *じゃなくてgchar *を返して呼び出し側で > g_free()してもらうという案もありますが、そっちもひと手間増え > ちゃいますよねぇ。 g_freeしてもらうのは、漏れる可能性が高いため、やめた方がいいと思うので バッファを渡す以下のような方向で修正しましたが、いかがでしょうか? #define RVAL2GLIBID(v, buf) (rbg_rval2glibid(&(v), &(buf), FALSE)) #define RVAL2GLIBID_ACCEPT_NIL(v, buf) (rbg_rval2glibid(&(v), &(buf), TRUE)) const gchar * rbg_rval2glibid(volatile VALUE *value, volatile VALUE *buf, gboolean accept_nil) { gchar *id, *p; if (accept_nil && NIL_P(*value)) return NULL; if (SYMBOL_P(*value)) { *buf = rb_String(*value); } else { StringValue(*value); *buf = rb_str_dup(*value); } RB_GC_GUARD(*buf); id = RSTRING_PTR(*buf); for (p = id; *p; p++) if (*p == '_') *p = '-'; return id; } /* 呼び出し側 */ static VALUE rg_set_foo(VALUE self, VALUE id) { VALUE buf; gtk_bar_set_foo(_SELF(self), RVAL2GLIBID(id, buf)); return self; } |