試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Vala言語でコマンド行オプションの解析と処理を行う(ページ3/3)

Vala言語でコマンド行オプションの解析と処理を行う(ページ2/3)」の続き。

オプション関係のデータをクラスにまとめた例

Vala言語でコマンド行オプションの解析と処理を行う(ページ2/3)」の1つ目の例の内、GLib.OptionEntry構造体のconst修飾子付きの配列を定義する方法では、データの書き込み先をインスタンスメンバ(静的でないメンバ)にしていたので「This access invalid outside of instance methods」となるが、データの書き込み先がクラスの静的メンバ(クラスメンバ)だとこうはならずに正しくコンパイルできる。ただし、その場合はオプションを受け取った結果はクラス1つにつき1つだけしか保持されない。
[任意]ファイル名: optioncontexttest3.vala

/*
 * OptionContextクラスのテスト
 * オプション処理用のクラスのインスタンスを生成しデータを静的メンバに格納する方法
 * valac --pkg posix optioncontexttest3.vala -o optioncontexttest3
 */

using Posix;

namespace OptionContextTest3
{
  class Options
  {
    GLib.OptionContext oc;
    static int size;
    static bool verbose;
    public
    Options ()
    {
      this.oc = new GLib.OptionContext ("- OptionContext test");
      // GLib.OptionEntry構造体
      // 1. 長いオプション(string)
      // 2. 短いオプション(char)
      // 3. フラグ(Glib.OptionFlags)
      // 4. オプションに対する引数の種類(GLib.OptionArg)
      // 5. 書き込み先(void *) out指定可
      // 6. 説明(string)
      // 7. オプション引数の表記(string)
      this.oc.add_main_entries (Options.option_entries, null);
    }
    // 静的メンバには書き込めるため、このような一覧が定義できる
    const GLib.OptionEntry[] option_entries =
    {
      {"size", 's', 0, GLib.OptionArg.INT, out Options.size, "set size", "SIZE"},
      {"verbose", 'v', 0, GLib.OptionArg.NONE, out Options.verbose, "be verbose", null},
      {null}
    };
    public void
    parse (ref unowned string[] args) throws GLib.OptionError
    {
      this.oc.parse (ref args);
    }
    public void
    show ()
    {
      print ("size: %d, verbose: %s\n", Options.size, Options.verbose.to_string ());
    }
  }
  int
  main (string[] args)
  {
    var opts = new Options ();
    try
    {
      opts.parse (ref args);
    }
    catch (GLib.OptionError e)
    {
      GLib.critical ("Failed to parse command line: %s", e.message);
      return EXIT_FAILURE;
    }
    opts.show ();
    return EXIT_SUCCESS;
  }
}

このようにしてしまうとインスタンスを作成している意味があまりないが、コマンド行オプションの解析結果を扱う上では格納先が1つだけでも問題はないため、そのクラスはメンバを全て静的メンバにして
[任意]ファイル名: optioncontexttest4.vala

/*
 * OptionContextクラスのテスト
 * オプション処理用のクラスで静的メンバのみを用いた方法
 * valac --pkg posix optioncontexttest4.vala -o optioncontexttest4
 */

using Posix;

namespace OptionContextTest4
{
  class Options
  {
    static GLib.OptionContext oc;
    static int size;
    static bool verbose;
    static bool is_inited;
    // GLib.OptionEntry構造体
    // 1. 長いオプション(string)
    // 2. 短いオプション(char)
    // 3. フラグ(Glib.OptionFlags)
    // 4. オプションに対する引数の種類(GLib.OptionArg)
    // 5. 書き込み先(void *) out指定可
    // 6. 説明(string)
    // 7. オプション引数の表記(string)
    static const GLib.OptionEntry[] option_entries =
    {
      {"size", 's', 0, GLib.OptionArg.INT, out Options.size, "set size", "SIZE"},
      {"verbose", 'v', 0, GLib.OptionArg.NONE, out Options.verbose, "be verbose", null},
      {null}
    };
    public static void
    init ()
    {
      Options.oc = new GLib.OptionContext ("- OptionContext test");
      Options.oc.add_main_entries (Options.option_entries, null);
      Options.is_inited = true;
    }
    public static void
    parse (ref unowned string[] args) throws GLib.OptionError
    {
      if (Options.is_inited)
        Options.oc.parse (ref args);
      else
        GLib.critical ("OptionContext not inited yet");
    }
    public static void
    show ()
    {
      print ("size: %d, verbose: %s\n", Options.size, Options.verbose.to_string ());
    }
  }
  int
  main (string[] args)
  {
    Options.init ();
    try
    {
      Options.parse (ref args);
    }
    catch (GLib.OptionError e)
    {
      GLib.critical ("Failed to parse command line: %s", e.message);
      return EXIT_FAILURE;
    }
    Options.show ();
    return EXIT_SUCCESS;
  }
}

のようにしてみた。ただ、これと比べてみても別の名前空間にデータを配置する「Vala言語でコマンド行オプションの解析と処理を行う(ページ1/3)」のやり方のほうがいいように見える。そのため、オプション関係のデータは別の名前空間に入れる方法をはじめに例として貼り付けることにした。

関連記事:

使用したバージョン:

  • Vala 0.9.4, 0.9.5
  • GLib 2.24.1