あおきです。

  In mail "[ruby-ext:00654] Re: (gtk) testgtk/ctree"
    Yasushi Shoji <yashi / yashi.com> wrote:

> > 次に(2) GC::start の # を除いて実行してみて下さい。
> 
> みごとに落ちますね。Rubyの GCの事は、まるでしらなかったのでいろいろ調べ
> てまわっているのですが、自分の無知をさらけだしてますね < patchたち。
> 
> 僕が投げた ctreeに関しての patchはぜんぶ破棄してくださいm(__)m
> 
> # っていうかこんなやつが、Ruby/Gtkの patch書いてて良いのか‥‥。(汗

自信持って書ける人はあまりいないですよ、きっと… ^^;;


で、添付したパッチでどうでしょう。
グローバルなハッシュを使って、ノードに渡したデータだけを
リファレンスカウント風に管理してます。
-------------------------------------------------------------------
あおきみねろう

--- org.ctree	Fri Dec  3 17:42:17 1999
+++ rbgtkctree.c	Fri Dec  3 18:30:27 1999
@@ -2,6 +2,7 @@
 
 static ID id_nodelist;
 
+/*
 static void
 ctree_node_mark(node)
      GtkCTreeNode *node;
@@ -9,13 +10,14 @@
     if (GTK_CTREE_ROW(node) && GTK_CTREE_ROW(node)->row.data)
 	rb_gc_mark(GTK_CTREE_ROW(node)->row.data);
 }
+*/
 
 VALUE
 make_ctree_node(node)
     GtkCTreeNode* node;
 {
     if (!node) return Qnil;
-    return Data_Wrap_Struct(gCTreeNode, ctree_node_mark, 0, node);
+    return Data_Wrap_Struct(gCTreeNode, 0, 0, node);
 }
 
 static GtkCTreeNode*
@@ -1101,13 +1103,49 @@
  *   node - tree node.
  *   data - custom data associated with a node.
  */
+
+static VALUE ctree_node_row_data;
+
+static void
+on_destroy_notice(data)
+    gpointer data;
+{
+    VALUE count;
+    int i;
+
+    /* decrement reference count */
+    count = rb_hash_aref(ctree_node_row_data, (VALUE)data);
+    i = FIX2INT(count);
+    if (i == 1)
+	rb_funcall(ctree_node_row_data, rb_intern("delete"), 1, (VALUE)data);
+    else {
+        count = INT2FIX(i - 1);
+        rb_hash_aset(ctree_node_row_data, (VALUE)data, count);
+    }
+}
+
 static VALUE
 ctree_node_set_row_data(self, node, data)
      VALUE self, node, data;
 {
-    gtk_ctree_node_set_row_data(GTK_CTREE(get_widget(self)),
-				get_ctree_node(node),
-				(gpointer)data);
+    VALUE count;
+
+    /* increment reference count */
+    count = rb_hash_aref(ctree_node_row_data, data);
+    if (NIL_P(count))
+    	count = INT2FIX(1);
+    else {
+        int i;
+
+        i = FIX2INT(count) + 1;
+	count = INT2FIX(i);
+    }
+    rb_hash_aset(ctree_node_row_data, data, count);
+
+    gtk_ctree_node_set_row_data_full(GTK_CTREE(get_widget(self)),
+				     get_ctree_node(node),
+				     (gpointer)data,
+				     on_destroy_notice);
     bind_ctree_node(self, node);
     return self;
 }
@@ -1532,6 +1570,9 @@
     rb_define_method(gCTree, "node_set_background", ctree_node_set_background, 2);
     rb_define_method(gCTree, "node_set_row_data", ctree_node_set_row_data, 2);
     rb_define_method(gCTree, "node_get_row_data", ctree_node_get_row_data, 1);
+    ctree_node_row_data = rb_hash_new();
+    rb_global_variable(&ctree_node_row_data);
+
     rb_define_method(gCTree, "node_moveto", ctree_node_moveto, 4);
     rb_define_method(gCTree, "node_is_visible?", ctree_node_is_visible_p, 1);
     rb_define_method(gCTree, "set_indent", ctree_set_indent, 1);