第 3 章 GLib 31
3.2 便利な関数
ここではGLibで提供されている関数をカテゴリ別にいくつか紹介します.
3.2.1 文字列操作関数
• g strdup
文字列をコピーして,新しく確保した領域へのポインタを返します. g c h a r* g _ s t r d u p (c o n s t g c h a r * s t r ) ;
• g strdup printf
指定したフォーマットと引数に与えたパラメータにより文字列を作成して, 新しく確保した領域へのポ インタを返します. sprintfと同じ働きをしますが, 予め作成される文字列用の領域を確保しておく必要 がありません.
g c h a r* g _ s t r d u p _ p r i n t f (c o n s t g c h a r * f o r m a t , v a _ l i s t a r g s ) ;
表3.1 GLibで定義された基本データ型
GLibで定義されたデータ型 対応する基本データ型
gboolean gint
gpointer void*
gconstpointer const void *
gchar char
guchar unsigned char
gint int
guint unsigned int
gshort short
gushort unsigned short
glong long
gulong unsigned long
gint8 signed char
guint8 unsigned char
gint16 signed short
guint16 unsigned short
gint32 signed int
guint32 unsigned int
gfloat float
gdouble double
• g strsplit
文字列stringを区切り文字delimiterで最大max tokens個に分割する関数です. g c h a r* * g _ s t r s p l i t (c o n s t g c h a r * s t r i n g ,
c o n s t g c h a r * d e l i m i t e r , g i n t m a x _ t o k e n s ) ;
• g new0
指定したデータ型struct typeのメモリ領域をn structs分確保し, 0で初期化して,その先頭アドレス を返します. この関数はg malloc0のマクロとして定義されています.
# d e f i n e g _ n e w 0 ( s t r u c t _ t y p e , n _ s t r u c t s ) \
( ( s t r u c t _ t y p e * ) g _ m a l l o c 0 ( ( (g s i z e) s i z e o f ( s t r u c t _ t y p e ) ) * \ ( (g s i z e) ( n _ s t r u c t s ) ) ) )
g p o i n t e r g _ m a l l o c 0 (g u l o n g n _ b y t e s ) ;
• g free
マクロg new0等で確保されたメモリ領域を解放する関数です.
v o i d g _ f r e e (g p o i n t e r m e m ) ;
• g strfreev
g strsplit等で確保された文字列の配列領域を解放する関数です.
v o i d g _ s t r f r e e v (g c h a r * * s t r _ a r r a y ) ;
3.2.2 ファイルアクセス関数
• g file test
GFileTestで定義されたファイルの状態を調べる関数です. 第2引数に与える値によって,ファイルが
存在するか,ファイルがディレクトリであるかなどを調べることができます.
g b o o l e a n g _ f i l e _ t e s t (c o n s t g c h a r * f i l e n a m e , G F i l e T e s t t e s t ) ;
GFileTestは次のように定義されています.
t y p e d e f e n u m {
G _ F I L E _ T E S T _ I S _ R E G U L A R = 1 < < 0 , G _ F I L E _ T E S T _ I S _ S Y M L I N K = 1 < < 1 , G _ F I L E _ T E S T _ I S _ D I R = 1 < < 2 , G _ F I L E _ T E S T _ I S _ E X E C U T A B L E = 1 < < 3 , G _ F I L E _ T E S T _ E X I S T S = 1 < < 4 } G F i l e T e s t;
• g dir open
ディレクトリをオープンする関数です. オープンしたディレクトリ内のファイル名を調べるには次の関 数g dir read nameを使用します.
G D i r* g _ d i r _ o p e n (c o n s t g c h a r * p a t h ,
g u i n t f l a g s ,
G E r r o r * * e r r o r ) ;
• g dir read name
関数g dir openでオープンしたディレクトリ内のファイル名を調べる関数です. 呼び出されるごとに順
にファイル名を返していきます. 最後まで読み込んだ場合はNULLが帰ります. G _ C O N S T _ R E T U R N g c h a r* g _ d i r _ r e a d _ n a m e (G D i r * d i r ) ;
• g dir close
関数g dir openでオープンしたディレクトリをクローズする関数です.
v o i d g _ d i r _ c l o s e (G D i r * d i r ) ;
サンプルプログラム
上記の関数を使用したプログラムの例をソース3–1に示します. このプログラムは引数に指定したディレク トリ内のファイルの一覧を表示するプログラムです.
ディレクトリのオープン(15行目)
関数g dir openの第1引数にオープンするディレクトリ名を指定してディレクトリをオープンします. 現在
の仕様では第2引数には0のみを指定することになっています. 第3引数にはGError構造体へのポインタを 指定しますが, エラーの詳細が必要ない場合にはNULLを与えておけばよいでしょう. ディレクトリのオープ ンに失敗するとNULLが返ってきます.
ディレクトリ内のファイルの表示(17–22行目)
17行目からのwhileループでは,関数g dir read nameによってオープンしたディレクトリ内のファイル名 を一つずつ取得していきます. そして関数g file testでファイルがディレクトリかどうか調べるために,関数 g build filenameを使用してファイル名にパスを追加しています. 関数g build filenameではファイル名用の メモリ領域が新しく領域確保されますので, 21行目で関数g freeで使用しなくなったメモリ領域を解放してい ます.
ディレクトリのクローズ(23行目)
最後に関数g dir closeでディレクトリをクローズしています.
以下にプログラムの実行結果を示します.
% gcc file-sample.c -o file-sample ‘pkg-config --cflags --libs glib-2.0‘
% ./file-sample . file-sample.c (file) file-sample.o (file) testfolder (folder) file-sample (file) Makefile (file)
%
ソース3–1 ファイル操作の例: file-sample.c
1 # i n c l u d e <g l i b . h >
2 # i n c l u d e <s t d l i b . h >
3
4 i n t m a i n (i n t ar g c , c h a r * a r g v [ ] ) {
5 G D i r * d i r ;
6 c o n s t g c h a r * n a m e ;
7 g c h a r * p a t h , * c u r r e n t d i r ;
8 g b o o l e a n i s _ d i r ;
9
10 i f ( a r g c ! = 2 ) {
11 g _ p r i n t ( " U s a g e : à . / f i l e - s a m p l e . c à d i r e c t o r y \ n " ) ;
12 e x i t ( 1 ) ;
13 }
14 c u r r e n t d i r = a r g v [ 1 ] ;
15 d i r = g _ d i r _ o p e n ( c u r r e n t d i r , 0 , N U L L ) ;
16 i f ( d i r ) {
17 w h i l e ( n a m e = g _ d i r _ r e a d _ n a m e ( d i r ) ) {
18 p a t h = g _ b u i l d _ f i l e n a m e ( c u r r e n t d i r , n a m e , N U L L ) ;
19 i s _ d i r = g _ f i l e _ t e s t ( p a t h , G _ F I L E _ T E S T _ I S _ D I R ) ;
20 g _ p r i n t ( " % s \ t ( % s ) \ n " , n a m e , ( i s _ d i r ) ? " f o l d e r " : " f i l e " ) ;
21 g _ f r e e ( p a t h ) ;
22 }
23 g _ d i r _ c l o s e ( d i r ) ;
24 }
25 r e t u r n 0 ;
26 }
3.2.3 Unicode に関する関数
• g locale to utf8
C言語中で文字列用のエンコーディングで与えられた文字列をUTF8でエンコーディングされた文字 列に変換する関数です. この関数によって新しい文字列用のメモリ領域が確保されますので,作成した 文字列が使用されなくなった場合には関数g freeなどでメモリ領域を解放してください.
g c h a r* g _ l o c a l e _ t o _ u t f 8 (c o n s t g c h a r * o p s y s s t r i n g ,
g s s i z e len ,
g s i z e * b y t e s _ r e a d , g s i z e * b y t e s _ w r i t t e n , G E r r o r * * e r r o r ) ;
• g locale from utf8
UTF8でエンコーディングされた文字列をC言語中で文字列用のエンコーディングに変換する関数で す. この関数によって新しい文字列用のメモリ領域が確保されますので, 作成した文字列が使用されな くなった場合には関数g freeなどでメモリ領域を解放してください.
g c h a r* g _ l o c a l e _ f r o m _ u t f 8 (c o n s t g c h a r * u t f 8 s t r i n g ,
g s s i z e len ,
g s i z e * b y t e s _ r e a d , g s i z e * b y t e s _ w r i t t e n , G E r r o r * * e r r o r ) ;
サンプルプログラム
GTK+のウィジェット内で扱われる文字コードはUTF8です. しかし, 関数g dir openなどで読み出した ファイル名やプログラムの引数として与えた文字列などは,ロケール指定の文字コードとなります. ここでは, プログラムの引数として与えた文字列をそのままラベルとして表示した場合と,文字コードをUTF8に変換し てラベルとして表示した場合を比較してみます. 図3.1はプログラムの実行例です.
% gcc utf8-sample.c -o utf8-sample ‘pkg-config --cflags --libs glib-2.0‘
% ./utf8-sample こんにちは世界
上のラベルはプログラムの引数に与えた文字列”こんにちは世界” をそのまま使用したラベルです. 下のラ ベルはプログラムの引数に与えた文字列の文字コードを関数g locale to utf8でUTF8に変更して使用したラ ベルです. 関数の第2引数には変換する文字列の長さを指定しますが,文字列を全て変換する場合には−1を
与えても構いません. 第3引数から第5引数までは通常NULLを指定しておいても構いません.
ソース3–2 文字コード変換: utf8-sample.c
1 # i n c l u d e <g t k / g t k . h >
2 # i n c l u d e <s t d l i b . h >
3
4 i n t m a i n (i n t ar g c , c h a r * a r g v [ ] ) {
5 G t k W i d g e t * w i n d o w , * l a b e l , * v b o x ;
6 g c h a r * n a m e , * u t f 8 n a m e ;
7
8 i f ( a r g c ! = 2 ) {
9 g _ p r i n t ( " U s a g e : à . / u t f 8 - s a m p l e . c às t r i n g \ n " ) ;
10 e x i t ( 1 ) ;
11 }
12 g t k _ i n i t ( & a r g c , & a r g v ) ;
13
14 w i n d o w = g t k _ w i n d o w _ n e w ( G T K _ W I N D O W _ T O P L E V E L ) ;
15 g t k _ w i n d o w _ s e t _ t i t l e ( G T K _ W I N D O W ( w i n d o w ) , " U T F 8 Ã S a m p l e " ) ;
16 g _ s i g n a l _ c o n n e c t ( G _ O B J E C T ( w i n d o w ) ,
17 " d e s t r o y " , G _ C A L L B A C K ( g t k _ m a i n _ q u i t ) , N U L L ) ;
18
19 v b o x = g t k _ v b o x _ n e w ( T R U E , 0 ) ;
20 g t k _ c o n t a i n e r _ a d d ( G T K _ C O N T A I N E R ( w i n d o w ) , v b o x ) ;
21
22 n a m e = a r g v [ 1 ] ;
23 l a b e l = g t k _ l a b e l _ n e w ( n a m e ) ;
24 g t k _ b o x _ p a c k _ s t a r t ( G T K _ B O X ( v b o x ) , l a b e l , T R U E , T R U E , 0 ) ;
25
26 u t f 8 n a m e = g _ l o c a l e _ t o _ u t f 8 ( n a m e , -1 , N U L L , N U L L , N U L L ) ;
27 l a b e l = g t k _ l a b e l _ n e w ( u t f 8 n a m e ) ;
28 g t k _ b o x _ p a c k _ s t a r t ( G T K _ B O X ( v b o x ) , l a b e l , T R U E , T R U E , 0 ) ;
29 g _ f r e e ( u t f 8 n a m e ) ;
30
31 g t k _ w i d g e t _ s h o w _ a l l ( w i n d o w ) ;
32 g t k _ m a i n ( ) ;
33
34 r e t u r n 0 ;
35 }
図3.1 文字コード変換のサンプルプログラム
3.2.4 その他の便利な関数
• g get home dir
ユーザのホームディレクトリを取得する関数です.
G _ C O N S T _ R E T U R N g c h a r* g _ g e t _ h o m e _ d i r (v o i d) ;
• g get current dir
現在のディレクトリを取得する関数です.
g c h a r* g _ g e t _ c u r r e n t _ d i r (v o i d) ;
• g path get basename
パスから最後のファイル名を返します. パスがディレクトリを指す場合には最後のディレクトリ名を返 します.
g c h a r* g _ p a t h _ g e t _ b a s e n a m e (c o n s t g c h a r * f i l e _ n a m e ) ;
• g path get dirname
パスから最後のファイル名を取り除いたディレクトリ部分を返します. g c h a r* g _ p a t h _ g e t _ d i r n a m e (c o n s t g c h a r * f i l e _ n a m e ) ;
• g build filename
引数に与えた文字列をファイル名用の区切り文字(例えば/)で結合して, 1つの文字列を作成します. 引 数の最後はNULLで終わる必要があります.
g c h a r* g _ b u i l d _ f i l e n a m e (c o n s t g c h a r * f i r s t _ e l e m e n t , . . . ) ;