GOptionContext

コマンドラインオプションは Linux では重要。
とりあえずよく見かける実装手段を自分で整理、したけど…

#include <stdio.h>
#include <getopt.h>

/* 
 * optarg, optind については unistd.h で定義されている 
 * getopt.h によってインクルードされる
**/

static struct
option options[] = {
    {"help",   no_argument, 0, 'h'},
    {"list",   no_argument, 0, 'l'},
    {"num", required_argument, 0, 'n'},
    {0, 0, 0, 0}
};

int
main (int argc, char *argv[]) {

    int opt, i;
    int idx = 0; /* 使い道が無いので気にしないほうがいい */

    /* 第三引数にアルファベットを指定 */
    while ((opt = getopt_long(argc, argv, "hln:", options, &idx)) != -1) {
        switch (opt) {
        case 'l':
            /* こうやって捕まえる */
            printf("-l or --list オプションです\n");
            break;
        case 'n':
            /* コロンを付けると値を受け取れる */
            printf("%s 行表示します\n", optarg);
            break;
        case 'h':
            /* Usage は自分で用意する */
            printf("ヘルプが表示されるかも...\n");
            return 0;
        case '?':
            return 1;
        }
    }
    /* オプションを省いた部分を処理 */
    for (i=optind; i<argc; i++) {
        printf("%d %s\n", i, argv[i]);
    }
    return 0;
}

option 構造体の中、getopt_long の引数、そして case 文。
いったい何度同じアルファベット指定を書かせるのよ。
間違いの元というか、整理していて自分が間違いまくったYO!

それじゃイカンと思ったのかどうかは知らないが。
GLib の GOptionContext は一箇所のみの指定になっていた。

#include <glib.h>
#include <stdio.h> /* stderr */

static gboolean _bool = 0;     /* 値を受ける必要が無いとき */
static gint     _num  = 0;     /* getopt と違い数値として受け取り */
static gchar*   _str  = NULL;  /* 文字列は破棄が必要、日本語はダメだった */

static GOptionEntry entries[] = {
    {"bool", 'b', 0, G_OPTION_ARG_NONE,   &_bool, "Show", NULL},
    {"num",  'n', 0, G_OPTION_ARG_INT,    &_num,  "Size", "<num>"},
    {"str",  's', 0, G_OPTION_ARG_STRING, &_str,  "Text", "<string>"},
    {NULL}
};

int
main (int argc, char *argv[]) {

    GError* error = NULL;
    GOptionContext* context;

    context = g_option_context_new ("After GApplication ?");
    g_option_context_add_main_entries (context, entries, NULL);
    if (!g_option_context_parse (context, &argc, &argv, &error)) {
        g_fprintf(stderr, "Error parsing options, try --help.\n");
        return 1;
    }
    /* 値を確認 */
    g_printf("boolean=%d, int=%d, string=%s\n", _bool, _num, _str);

    /* 後は GApplication ? */

    g_free(_str);
    g_option_context_free(context);
    return 0;
}
/* output

$ ./a.out
boolean=0, int=0, string=(null)

$ ./a.out -b --num 675 -s Daytona
boolean=1, int=675, string=Daytona

$ ./a.out -h
Usage:
  a.out [OPTION...] After GApplication ?

Help Options:
  -h, --help             Show help options

Application Options:
  -b, --bool             Show
  -n, --num=<num>        Size
  -s, --str=<string>     Text

*/

GOptionEntry が少し面倒、と思ったら大間違いだった。
まさかの Usage 全自動生成、しかも細かい。
Python の optparse 同様に -h –help は勝手に作ってくれる。

変更したくなったら一箇所だけ書き換えればいいのは本当に嬉しい。
Usage にさえ反映されるので「やっちまった…」は確実に減る。

GOptionContext ってこんなに凄かったのか。
C 言語標準ライブラリでゴリゴリ書くなんてアホみたい。
せっかく整理したけどもう getopt を使うことは無いがや。

しかし別途というかオプション以外の引数や数を得る関数が何も無い。
そういうのは GApplication でヤレということでいいのかな?