From: Masahiro S. ()
<sa...@to...> - 2006-05-19 19:15:26
|
酒井です。 From: Masao Mutoh <mu...@hi...> Date: Sat, 20 May 2006 02:37:56 +0900 > むとうです。 > > 実際に現在のコードで問題が起こる例を探してみました。 > > > > fsel = Gtk::FileSelection.new > > fsel.ok_button.signal_connect('clicked'){} > > GC.start > > fsel.ok_button.clicked > > > > この場合には返り値との間に親子関係が成立することがあらかじめ分かってい > > るので、ok_button内でG_CHILD_ADDすれば良いですが、そうでない場合にはよ > > り悩ましいと思います。 > > 手元で試しましたが、少なくともCVS版では落ちません。 > 理論上落ちるという話でしょうか。偶然なのかな。 > なんか対応したっけ・・・・忘れてますが(苦笑)。 私の手元の環境では (eval):11: warning: GRClosure invoking callback: already destroyed が出ました。環境は * 昨日のCVSのRuby-GNOME2 * ruby 1.9.0 (2006-01-19) [i386-cygwin] * Cygwin標準パッケージのgtk+ 2.6.10, glib 2.6.6 です。 > まぁ、でも理論的には、CHILD_ADD(CHILD_SETかな)すべし、 > というのが正解だとは思うんですけど。 親子関係が成立すると予めわかっている場合にはそれで良いのですが、 そうでない場合にはどうします? 例えば、このボタンがok_buttonメソッドの返り値としてではなく、 「現在のマウスポインタの直下のウィジェットを返す」という関数の返り値 として渡ってきたとしたら…… > > ではもう一つ見つけた例を。 > > > > view = Gtk::TextView.new > > iter = view.get_iter_at_location(0,0) > > iter.buffer.signal_connect('changed'){ puts "changed" } > > GC.start > > view.insert_at_cursor("foo") > > こちらも、私の環境では普通に動きますね・・・。 同じく私の手元の環境ではエラーになりました。 > こちらも理論的には、iter.bufferでCHILD_SETすべし、というのが正解だとは思うんですけど。 そう簡単にはいかないよう少し嫌らしい例にしてあります(^^; 普通iterはbufferよりも寿命の短いオブジェクトなので、iterからbufferを参 照させるだけでは解決にはならず、解決にはbufferの本当の所有者であるview からbufferを参照させなければなりません。しかし、iter自身はviewへの参照 を持っていないので、iter.bufferの変更だけで対処することは出来ません。 一つの解決法はGtk::TextView.newでbufferをCHILD_SETすることでしょう。 iter.bufferの変更という局所的な変更で解決出来ないのは良い気分ではない ですが、とにかく一応は解決は出来ます。 しかし、もし同様の状況で仮にviewからbufferへの参照を得るAPIも存在しな いとしたらどうでしょうか。その場合にはこのような方法すら取れないわけ で…… > > それと、Gtk::Container(とその派生クラス)ではmark時にgtk_container_forallで > > 子供を列挙してmarkすべきですね。そうすれば、コンテナの場合の親子関係に > > ついては個別に対処する必要はなくなると思います。 > > それって、例えばGtk::FileSelection.newしたタイミングで実施するイメージですかね。 違います。 RubyのGCのmark phaseでrb_gc_mark()するという話です。 # ついでに、オブジェクトのプロパティを同様にmarkするのも良さそう。 # parentもプロパティなので須藤さんの案を包摂しますし。 -- 酒井 政裕 / Masahiro Sakai |