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

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

Vala言語で外部プロセスを実行する(簡単な例・メモ)

ここではVala言語を用いて外部プロセスを実行するための処理を扱う。
元々GLibの機能なので、GLibのC言語APIから直接使用することもできるが、Vala言語ではより扱いやすくなっている。
ここでは最もシンプルな「コマンド行文字列から外部プロセスを実行する」形についてのメモを扱う。

  1. GLib.Process.spawn_command_line_async() - 最もシンプルな呼び出し形式・非同期処理
  2. GLib.Process.spawn_command_line_sync() - 同期処理で出力とステータス値が取得できる
    1. 返されるステータス値とプロセス終了時のステータスについて
    2. コマンド出力内の日本語の文字化けについて
  3. 関連:「spawn」の意味

GLib.Process.spawn_command_line_async() - 最もシンプルな呼び出し形式・非同期処理

public static bool spawn_command_line_async (string command_line) throws SpawnError;

GLib.Process.spawn_command_line_async()を使用すると指定されたコマンド行文字列をもとにして外部プロセスを実行するが、その終了を待たずに先の処理に進み(非同期で処理する)、子プロセスのステータス値(後述)を知ることはできない。
子プロセスの実行に失敗すると例外GLib.SpawnErrorが発生するので、try-catch文により処理する。これは他の外部プロセス起動関数でも同様となる。
成功したかどうかは真偽値(bool型)の戻り値としても得られる。

GLib.Process.spawn_command_line_sync() - 同期処理で出力とステータス値が取得できる

public static bool spawn_command_line_sync (string command_line, out string standard_output = null, out string standard_error = null, out int exit_status = null) throws SpawnError;

GLib.Process.spawn_command_line_sync()を使用すると指定されたコマンド行文字列を実行し、終了まで待機する。その際には「out」付きで受け取った

の変数をそれぞれ書き換える。
発生する例外とその処理、戻り値についてはGLib.Process.spawn_command_line_async()と同様。

返されるステータス値とプロセス終了時のステータスについて
Pythonで外部プロセスを起動して出力と戻り値を処理する」で書いたように、Pythonのsubprocessモジュールを用いた場合にはメンバ関数wait()の戻り値がプロセスの終了時の戻り値となっていたが、ここで扱われる「ステータス値」は「wait」のmanページなどで扱われている一般的なプロセス終了時の状態情報で、終了時の戻り値以外の情報を含んでいる。
C言語ではWEXITSTATUSというマクロを用いて終了ステータスを取得するが、Vala言語ではGLib.Process.exit_status()からマクロを呼び出すことになる。*1
他のマクロについても同様の関数がGLib.Process名前空間に用意されている。
[引用]ファイル名: vala-0.7.4/vapi/glib-2.0.vapi より

namespace Process {
(中略)
 /* these macros are required to examine the exit status of a process */
 [CCode (cname = "WIFEXITED", cheader_filename = "sys/wait.h")]
 public static bool if_exited (int status);
 [CCode (cname = "WEXITSTATUS", cheader_filename = "sys/wait.h")]
 public static int exit_status (int status);
 [CCode (cname = "WIFSIGNALED", cheader_filename = "sys/wait.h")]
 public static bool if_signaled (int status);
 [CCode (cname = "WTERMSIG", cheader_filename = "sys/wait.h")]
 public static ProcessSignal term_sig (int status);
 [CCode (cname = "WCOREDUMP", cheader_filename = "sys/wait.h")]
 public static bool core_dump (int status);
 [CCode (cname = "WIFSTOPPED", cheader_filename = "sys/wait.h")]
 public static bool if_stopped (int status);
 [CCode (cname = "WSTOPSIG", cheader_filename = "sys/wait.h")]
 public static ProcessSignal stop_sig (int status);
 [CCode (cname = "WIFCONTINUED", cheader_filename = "sys/wait.h")]
 public static bool if_continued (int status);
}

「cname」のマクロ名が1行下の関数名に対応している。

コマンド出力内の日本語の文字化けについて
GLib.Process.spawn_command_line_sync()を用いてコマンドを実行したときの出力に日本語が含まれると「?」に化ける。
その対処としてはLC_CTYPEのロケールGLib.Intl.setlocale()で指定する。

weak string? lc_ctype = GLib.Environment.get_variable ("LC_CTYPE");
if (lc_ctype != null)
  GLib.Intl.setlocale (GLib.LocaleCategory.CTYPE, lc_ctype);

ただし、GTK+アプリケーションでGUI部品(テキストビューなど)に出力する場合は代わりに別の処理を行う(ここでは扱わない)。

関連:「spawn」の意味

「spawn(スポーン)」には魚などが「産卵する」という意味があり、親プロセスが子プロセスを卵のように「産む」というイメージで名前が付けられているものと思われる。
(2015/1/14)manページのリンク先を修正

参考URL:

使用したバージョン:

  • Vala 0.7.4

*1:中間ファイルとしてのC言語のコードにおいてこれらのマクロが用いられる