[[AI対戦サーバープログラム作成のヒント]]

*その1 プログラム内で別のプログラムを実行する [#s41cd6f5]
**子プロセスを作成する [#he190ebc]

ここでは、ある(親)プロセスの中で、別の(子)プロセスを実行をします。~
まず、子プロセスとなるプログラムを作ります。~

 #include <stdio.h>
 
 int main(void)
 {
   printf("child is called.\n");
 
   return 0;
 }

なんてことはない、Hello Worldプログラムと一緒ですね。~
これをコンパイルして出来た実行ファイルを「child.exe」としておきます。~

**親プロセスを作成する [#ra927fdc]
では、本題の親となるプログラムを作ります。~
まずは前半部分の、main関数です。~

 #include <stdio.h>
 #include <windows.h>
 
 int execute(LPTSTR commandLine);
 
 int main()
 {
   LPTSTR commandLine = TEXT("child.exe"); //子プログラム
   int r;
 
   printf("parent start.\n");
 
   r = execute(commandLine);
 
   printf("parent end.\n");
   return r;
 }

<windows.h>をインクルードすることで、LPTSTR型やTEXT関数などが使えています。~
WinAPIの「お約束」みたいなものだと思うので、気にしないでください。~
(気になった人は各自調べてみてください)~
commandLineには実行するプログラムの名前が入っています。

execute関数だけは、自分で定義しています。この中身を確認していきます。

 int execute(LPTSTR commandLine)
 {
   HANDLE childProcess = NULL;
   STARTUPINFO si = { sizeof(STARTUPINFO) };
   PROCESS_INFORMATION pi = {};
 
   if (!CreateProcess(
     commandLine, //実行するファイル名
     NULL,	//実行時引数の指定
     NULL,	//プロセスのセキュリティー記述子
     NULL,	//スレッドのセキュリティー記述子
     FALSE,	//ハンドルを継承しない(子は親を操作できない)
     0,		//作成フラグ
     NULL,	//環境変数は引き継ぐ
     NULL,	//カレントディレクトリーは同じ
     &si,
     &pi))
   { return -1; }
 
   // 子プロセス起動成功
   childProcess = pi.hProcess;
 
   // 不要なスレッドハンドルをクローズする
   if (!CloseHandle(pi.hThread))
   { return -1; }
 
   // 子プロセスの終了待ち
   DWORD r = WaitForSingleObject(childProcess, INFINITE);
 
   // 子プロセスの終了コードを取得、出力
   DWORD exitCode;
   if (!GetExitCodeProcess(childProcess, &exitCode))
   { return -1; }
 
   printf("exitCode=%d/%x\n", exitCode, exitCode);
 
   CloseHandle(childProcess);
 
   return exitCode;
 }

HANDLE や STARTUPINFO 、 PROCESS_INFORMATION は、子プロセスを作成するために必要なものなので、深く考えないほうがいいです。~
同じく、createProcess関数の引数も1番目と2番目以外は考える必要はないと思います。~
1番目に実行ファイルの名前を、2番目に実行時引数を文字列で与えます。~

子プロセスの起動に成功したら、子プロセスのスレッドハンドルは不要なので閉じ、子プロセスの終了を待ちます。~
WaitForSingleObject関数の第2引数には、タイムアウト時間(ms)を入れます。~
INFINITEは無制限を表します。~

子プロセスが終了したら、終了コード(子プロセスのmainからの返り値)を取得して、子プロセスのハンドルを閉じます。~
終了コードが必要ないならば、取得する必要はありません。~
毎回子プロセスを立ち上げて、その返り値を使うのであれば、この手法を使うといいでしょう。

**実行結果 [#qdec1525]

最後にこのプログラムの実行結果を確認します。~
2つの実行ファイルを同じフォルダに入れて親側のプログラムを実行させます。~

 parent start.
 child is called.
 exitCode=0
 parent end.

親プロセスの中で、子プロセスが呼び出されているのがわかりますね。~

**補足 [#u1db40b3]
記述する所がなかったので、こちらで書きますが、<windows.h>ではBOOL型が定義されています。~
(内部的にはint型と同じ)~
 typedef BOOL int
なので、C言語でもBOOL型やTRUE,FALSEといったワードが使用可能です。~
(C++のbool型とは異なる型なので注意)~

WaitForSingleObject関数の返り値ですが、成功するとおそらく
WaitForSingleObject関数の返り値ですが、成功するとおそらく、

-WAIT_OBJECT_0
-WAIT_TIMEOUT

のどちらかが返ると思います。タイムアウトの判定は、返り値がWAIT_TIMEOUTかどうかで判断が出来ます。

前回:[[なし(目次へ)>AI対戦サーバープログラム作成のヒント]] 次回:[[その2 パイプを使ってみる>AI対戦サーバープログラム作成のヒント/パイプの生成]]

*コメント [#iddef60f]
#comment

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS