|
From: Masaaki A. <mas...@gm...> - 2011-12-03 03:06:17
|
青柳です。 gtk_widget_path_iter_list_classes gtk_widget_path_iter_list_regions にて、戻り値の開放を要素はせず、リストのみ行うとのことなので、単純に対応したものを https://github.com/ruby-gnome2/ruby-gnome2/pull/62 で提案しました。が、今度は gtk_file_chooser_get_files にて、要素はg_object_unrefを、リストはg_slist_freeしろとのことで、色々なパターンが ありそうです。そのため、柔軟に対応できるように struct gobjgslist2rval_args { GSList *list; GFreeFunc free_list; GFreeFunc free_elem; }; static VALUE gobjgslist2rval_body(VALUE data) { struct gobjgslist2rval_args *args = (struct gobjgslist2rval_args *)data; GSList *i; VALUE ary; ary = rb_ary_new(); for (i = args->list; i != NULL; i = i->next) rb_ary_push(ary, GOBJ2RVAL(i->data)); return ary; } static VALUE gobjgslist2rval_ensure(VALUE data) { struct gobjgslist2rval_args *args = (struct gobjgslist2rval_args *)data; GSList *i; if (args->free_elem) for (i = args->list; i != NULL; i = i->next) args->free_elem(i->data); if (args->free_list) args->free_list(args->list); return Qnil; } VALUE rbgutil_gobjgslist2rval(GSList *const list, GFreeFunc free_list, GFreeFunc free_elem) { struct gobjgslist2rval_args args = {list, free_list, free_elem}; return rb_ensure(gobjgslist2rval_body, (VALUE)&args, gobjgslist2rval_ensure, (VALUE)&args); } のようなものを定義し、マクロとしては #define GOBJGSLIST2RVAL(list) \ rbgutil_gobjgslist2rval(list, (GFreeFunc)NULL, (GFreeFunc)NULL) #define GOBJGSLIST2RVAL_FREE(list, free_list, free_elem) \ rbgutil_gobjgslist2rval(list, (GFreeFunc)free_list, (GFreeFunc)free_elem) のように開放有り無しの2種類定義しておいて、解放する場合はその関数を渡せるようにしたら いかがでしょうか? よろしければ、現在のものはdeprecatedとしてファイルを分けていって、置き換えていこうと思います。 (例:rbgutil.c -> rbgutildeprecated.c) |
|
From: Kouhei S. <ko...@co...> - 2011-12-03 05:35:42
|
須藤です。 In <CAM...@ma...> "[ruby-gnome2-devel-ja] リストからrubyオブジェクトへの変換について" on Sat, 3 Dec 2011 12:06:09 +0900, Masaaki Aoyagi <mas...@gm...> wrote: > gtk_widget_path_iter_list_classes > gtk_widget_path_iter_list_regions > にて、戻り値の開放を要素はせず、リストのみ行うとのことなので、単純に対応したものを > https://github.com/ruby-gnome2/ruby-gnome2/pull/62 > で提案しました。が、今度は > gtk_file_chooser_get_files > にて、要素はg_object_unrefを、リストはg_slist_freeしろとのことで、色々なパターンが > ありそうです。そのため、柔軟に対応できるように ... > のように開放有り無しの2種類定義しておいて、解放する場合はその関数を渡せるようにしたら > いかがでしょうか? > よろしければ、現在のものはdeprecatedとしてファイルを分けていって、置き換えていこうと思います。 > (例:rbgutil.c -> rbgutildeprecated.c) はい、基本的にはそれでよいと思います。 > struct gobjgslist2rval_args { > GSList *list; > GFreeFunc free_list; > GFreeFunc free_elem; > }; GSListを解放する方法はg_slist_free()しかないと思うので、 GFreeFuncなfree_listではなく、gbooleanで十分じゃないかと思い ました。 もしかしたら、要素を解放するときはリスト自体も削除する、とい う風にしてしまって、free_list自体をなくしてしまってもいいか もしれません。要素だけを解放したい時ってあるのかしら。リスト の中に解放済み要素だけあっても意味無いですよねぇ。 > static VALUE > gobjgslist2rval_body(VALUE data) > { > struct gobjgslist2rval_args *args = (struct gobjgslist2rval_args *)data; > GSList *i; > VALUE ary; > > ary = rb_ary_new(); > for (i = args->list; i != NULL; i = i->next) > rb_ary_push(ary, GOBJ2RVAL(i->data)); > > return ary; > } 実は、個人的には GSList *node; ... for (node = args->list; node; node = g_slist_next(node)) ... という書き方が好みだったりします。 (より適切な名前を使っていると思うので。) もしよければ採用してもらえると嬉しいです。 > のようなものを定義し、マクロとしては > > #define GOBJGSLIST2RVAL(list) \ > rbgutil_gobjgslist2rval(list, (GFreeFunc)NULL, (GFreeFunc)NULL) > #define GOBJGSLIST2RVAL_FREE(list, free_list, free_elem) \ > rbgutil_gobjgslist2rval(list, (GFreeFunc)free_list, > (GFreeFunc)free_elem) GSListにはGObject以外にもgchar *とかも入っていそうなので、解 放する関数をGFreeFuncでカスタマイズできるようにするなら、最 初の「GOBJ」は抜いたほうがいいかなぁと思いました。 |
|
From: Masaaki A. <mas...@gm...> - 2011-12-06 15:08:48
|
青柳です。 まだ確認してないのでpull requestはまだですが、取り敢えず https://github.com/masaakiaoyagi/ruby-gnome2/commits/glist2rval のような感じで実装してみました。 * 要素の変換関数も渡せるようにして、公開するシンボルを少なくする * rbg_filename_gslist_to_array_freeもまとめられるようにする * prefixをrbgutilからrbgにする といったところを当初の予定から変更しています。 何か問題がありそうでしたら、ご指摘ください。 ちなみに、GListとGSListの現在の定義が struct GList { gpointer data; GList *next; GList *prev; }; struct GSList { gpointer data; GSList *next; }; となっていて、もしGListがGSList+prevという構造であることが保証されていれば GList版とGSList版で関数を分けずにまとめられるなぁとか思ったのですが、 そんな保証されてないですよね? |
|
From: Kouhei S. <ko...@co...> - 2011-12-07 11:56:11
|
須藤です。 In <CAM...@ma...> "Re: [ruby-gnome2-devel-ja] リストからrubyオブジェクトへの変換について" on Wed, 7 Dec 2011 00:08:37 +0900, Masaaki Aoyagi <mas...@gm...> wrote: > まだ確認してないのでpull requestはまだですが、取り敢えず > https://github.com/masaakiaoyagi/ruby-gnome2/commits/glist2rval > のような感じで実装してみました。 > * 要素の変換関数も渡せるようにして、公開するシンボルを少なくする > * rbg_filename_gslist_to_array_freeもまとめられるようにする > * prefixをrbgutilからrbgにする > といったところを当初の予定から変更しています。 だいたいよいと思います! いくつか気になった点はこんなところです。 * ToRValueFuncはRGConvFuncとか「RG」(RBG?)プレフィックス みたいにした方がよさそう。(関数名のプレフィックスと同じ ような感じで。) * GType固定にしないで、gpointerを渡すようにして、使う人が 好きなデータを渡せるようにするとGLibっぽくてよいかも。 (でも、オーバースペックかもしれない。) 例えば、g_list_sorted_with_data()がそういうインターフェ イスで、他にもいろいろあるはず。 http://developer.gnome.org/glib/stable/glib-Doubly-Linked-Lists.html#g-list-sort-with-data * #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ ... #ifdef __cplusplus } #endif /* __cplusplus */ の代わりに G_BEGIN_DECLS ... G_END_DECLS を使うのがGLibっぽくてよさそう。 http://developer.gnome.org/glib/stable/glib-Miscellaneous-Macros.html#G-BEGIN-DECLS:CAPS http://developer.gnome.org/glib/stable/glib-Miscellaneous-Macros.html#G-END-DECLS:CAPS > ちなみに、GListとGSListの現在の定義が > struct GList { > gpointer data; > GList *next; > GList *prev; > }; > struct GSList { > gpointer data; > GSList *next; > }; > となっていて、もしGListがGSList+prevという構造であることが保証されていれば > GList版とGSList版で関数を分けずにまとめられるなぁとか思ったのですが、 > そんな保証されてないですよね? そうですねぇ。 まず変わることはないと思いますが、そこに依存するのはやめた方 がいいと思います。 |
|
From: Masaaki A. <mas...@gm...> - 2011-12-03 07:27:56
|
青柳です。
> はい、基本的にはそれでよいと思います。
ありがとうございます!
>> struct gobjgslist2rval_args {
>> GSList *list;
>> GFreeFunc free_list;
>> GFreeFunc free_elem;
>> };
>
> GSListを解放する方法はg_slist_free()しかないと思うので、
> GFreeFuncなfree_listではなく、gbooleanで十分じゃないかと思い
> ました。
>
> もしかしたら、要素を解放するときはリスト自体も削除する、とい
> う風にしてしまって、free_list自体をなくしてしまってもいいか
> もしれません。要素だけを解放したい時ってあるのかしら。リスト
> の中に解放済み要素だけあっても意味無いですよねぇ。
確かに、あまりfree_listの存在意義はないかもしれません。ただ、
* リファレンスを見て、使えという関数をコピペすればいいので単純
* もしかしたら、解放されるタイミングで何か処理を入れたくなるかもしれない
という感じで今の仕様としました。
>> static VALUE
>> gobjgslist2rval_body(VALUE data)
>> {
>> struct gobjgslist2rval_args *args = (struct gobjgslist2rval_args *)data;
>> GSList *i;
>> VALUE ary;
>>
>> ary = rb_ary_new();
>> for (i = args->list; i != NULL; i = i->next)
>> rb_ary_push(ary, GOBJ2RVAL(i->data));
>>
>> return ary;
>> }
>
> 実は、個人的には
>
> GSList *node;
> ...
> for (node = args->list; node; node = g_slist_next(node))
> ...
>
> という書き方が好みだったりします。
> (より適切な名前を使っていると思うので。)
>
> もしよければ採用してもらえると嬉しいです。
現状に合わせただけなので、g_slist_nextを使用するようにします。
>> のようなものを定義し、マクロとしては
>>
>> #define GOBJGSLIST2RVAL(list) \
>> rbgutil_gobjgslist2rval(list, (GFreeFunc)NULL, (GFreeFunc)NULL)
>> #define GOBJGSLIST2RVAL_FREE(list, free_list, free_elem) \
>> rbgutil_gobjgslist2rval(list, (GFreeFunc)free_list,
>> (GFreeFunc)free_elem)
>
> GSListにはGObject以外にもgchar *とかも入っていそうなので、解
> 放する関数をGFreeFuncでカスタマイズできるようにするなら、最
> 初の「GOBJ」は抜いたほうがいいかなぁと思いました。
すみません。言葉足らずでしたが、GOBJ2RVALを型によって変更する必要があるので、
要素の型の数だけ同様のものを用意します。
(たぶんensureは共通にできるとは思っています)
|