|
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;
}
|