生産ラインにおける制御用プログラム開発ツール
|
山田周司
目 次
1. パケット管理DLLの制約
2. ロジェクト管理ファイル
3. スクリプト
4. スクリプト処理プログラム
5. パケットからの関数呼び出し
6. スクリプトから呼び出される関数のパラメータと使い方
7. パケット処理プログラムメンバ関数
8. パケット管理DLLメンバ関数
変 更 履 歴
バージョン | 日付 | 変更箇所 | 改 正 内 容 |
1.0 | H14.02.17 | 全 | 新規作成 |
1.01 | H14.02.26 | 1. | 1パケットのサイズ 最大131,072バイト → 512kB |
〃 | 〃 | 1. | 共有メモリサイズ 最大256kByte → 4096kB |
1.03 | H14.06.12 | 7. | tracelog.txt出力使用・不使用を選択可 |
〃 | 〃 | 7. | Trace()関数の引数の形式変更 |
1.パケット管理DLLの制約
(1) スレッド数 最大128
(2) パケットの種類 最大256
(3) 使用可能なパケットの数 最大8192
(4) 1パケットのサイズ 最大512kB
(5) 共有メモリサイズ 最大4096kB
2. プロジェクト管理ファイル
(1) ファイル名 prjfile.txt
(2) 記述内容
セクション
記述項目 |
説 明 |
[ThreadId]
<スレッド名> <id> <パス名> |
スレッド名、識別ID、ソース出力パスを定義する。
idは 1〜4096 の範囲とする。 |
[WindowId]
<ウィンドウ名> <id> <パス名> |
ウィンドウ名、識別ID、ソース出力パスを定義す
る。idは 1〜4096 の範囲とする。 |
[PacketId]
<パケット名> <id> |
パケット名、識別IDを定義する。
idは 1〜4096 の範囲とする。 |
[DllPath]
<パス名> |
アプリケーションのexeファイル、及びパケット
管理DLLを置くパスを定義する。 |
[ScriptPath]
<パス名> |
スクリプトを置くパスを定義する。 |
(3) ディレクトリ構成とパスの指定方法
ユーザは基準となるフォルダの下に以下のようにフォルダを作成する。
プロジェクト管理ファイルで指定するパスは <base
dir>を基準としたパス名とする。
<base dir> ---+---- <パス名1>
アプリケーション1のソース格納フォルダ
|
PktCtrl.h, MemDll.h, <スレッド名>.h, <スレッド名>.cpp,
|
及びコンパイラがビルドに使用するファイルを置く。
| <パス名2>
アプリケーション2のソース格納フォルダ
|
・
|
・
+---- <DllPath> dll、exeファイル格納フォルダ
|
ShmPkt.dll, *.exe を置く。pktcode.dat格納
+---- <ScriptPath> スクリプト処理プログラム、スクリプト、及びライブラリ
を格納するフォルダ
prjfile.txt,<パケット名>.pkt, CvScript.exe,
ShmPkt.lib, PktCtrl.lib を置く。
その他CvScript.exeにより生成される以下のファ
イルもここに格納される。
threaddef.h, pkttbl.h, pkttbl.cpp,funclist.txt
小規模なシステムでは<パス名1>〜<ScriptPath>までを1つのフォルダにまとめ、全て同じパス名の
指定も可能とする。
3.スクリプト
(1) ファイル名
<パケット名>.pkt
<パケット名>はプロジェクト管理ファイルで定義したパケット名とする。未定義の名称で作成した
ファイルはその後の処理で無視される。
(2) 文の終わり
";" セミコロンは文の終わりを示す。
(3) 変数
スクリプトで変数を宣言するとパケットに領域が確保される。
◇
変数の型
bool, long,
double の3種類のみとする。
◇
変数宣言
var
<型> <変数名> ;
var
struct <型> <変数名> ;
型としてbool, long, double を指定するとスクリプト上で参照,更新が可能となる.
その他の char型,配列(bool, long, double の配列を含む),定義済みの型,および
構造体を指
定することも可能とするが,データの受け渡し用エリアがパケットに確保されるのみで,スクリプ
トからこれを参照することはできない。
var 文はスクリプトの先頭部分にまとめて記述する。
(4) 式
演算子と"(" , ")" ,変数,数値定数の組み合わせ.演算子には次のものがある。
単項演算子
"-", "!"
二項演算子
"+", "-", "*", "/", "==", "!=", ">", "<", ">=", "<=", "&&",
"||"
演算子の優先順位はC言語に準ずるものとする。
(5) ラベル定義
<ラベル名>:
(6) goto文
goto <ラベル名>
;
(7) 代入文
<変数> = <式> ;
(8) if 文
if (<式>) <文> [ else
<文> ]
(9) 関数呼び出し
[ <変数> = ] <スレッド名>.<関数名>(<実行方法>)
;
スレッドの関数を呼び出す。
<変数>が指定されていれば,復帰値を<変数>に格納する。
<実行方法>は,スクリプトから関数を呼び出して結果を受け取る方法を指定する。
(10) 複文
{ <文> … }
(11) end 文
end;
パケットスクリプトを終了して自身を廃棄する。
(12) NULLステートメント
";"のみはエラーとなる。
(13) 名前空間
変数名,関数名,ラベル名の名前空間は同じであり,これらの個々の名前は,パケット全体をスコ
ープとする。スレッド名とパケット名の名前空間は同じであり,システム全体をスコープとする。
(14) システム変数
パケット上には変数宣言とは別にシステム変数の領域が確保され、スクリプト上から参照が可能と
する。errorNoは更新も可能である。
long serialNo;
パケット識別No.:システム全体でユニークな0以外の値
long parentNo;
CreatePKTにより生成された場合生成元のパケット識別No., その他は0 と
する。
long currentStep 実行中の命令アドレス
long currentThread;
現在パケットを占有しているスレッドのID
long priority;
(将来用)
long errorNo;
システムエラー※の番号を示す。
long errorThread;
システムエラー※が発生したスレッドIDを示す。
long timeOut;
(将来用)
※ :システムエラーはパケット処理プログラムで発生するエラーを指す。
(15) 特殊な関数のパラメータ
以下の関数は特別な処理を実行するものとする。4.(2)
参照
Wait(PKT_SELF) : 非同期実行の終了を待って結果を受け取る。PKT_SELF
は常に固定とする。
CreatePKT(<パケット名>)
: サブルーチンとしてのパケット <パケット名>を生成する。
(将来対応予定の機能)... パラメータとして自分自身 を指定すると自身のクローンを
生成し実行する。この場合、サブルーチンパケットの実行はCreatePKTの次のステップ
から開始される。
WaitPKT(<パケット名>) :
CreatePKTで生成されたパケット<パケット名>の終了を待って結果を
受け取る。
PassTo(<パケット名>)
: CreatePKTで生成されたパケットが自身の実行結果を生成元パケットへ
渡すための関数。
(16) コメント
"//" が出てきたら行の後ろ側はコメントとみなされる。
(17) スレッド名,パケット名,関数名, 変数名,ラベル名
半角英数字または“_”28文字以内、先頭は数字以外とする。
4.スクリプト処理プログラム
(1) 入力ファイル
◇
プロジェクト管理ファイル prjfile.txt
◇
パケットスクリプト
<パケット名>.pkt
◇
スレッドのヘッダ
<スレッド名>.h
スレッドのソース
<スレッド名>.cpp
スクリプト処理プログラムにより生成されたヘッダまたは、これにユーザが記述を追加、修正し
て変更を加えたもの。本ファイルが存在しない場合はスレッドを新規に作成するものと見なされる。
(2) 生成ファイル
生成ファイルの中で"//{{","//}}"に続き同じ名前のつくコメントで挟まれた範囲はスクリプト処
理プログラムが読み込み解釈する部分であり、ユーザが変更してはならない。
◇命令コードファイル
pktcode.dat
スクリプトから生成された命令コードが格納される。全スクリプトのデータが1つのファイルに保
存される。
◇パケット構造定義ヘッダファイル pkttbl.h
プロジェクト管理ファイルに定義されたパケット名、IDと同じものが#define
に出力され、その
後ろに構造体の定義が出力される。
// pkttbl.h
// this file is generated by program
// don't edit
#if !defined(PKTTBL_H__INCLUDED_)
#define PKTTBL_H__INCLUDED_
#define GENERATE_TIME "<MMDD$HHMMSS>"
//{{PKT_TBL
#define <パケット名1> <id1>
#define <パケット名2> <id2>
・
・
struct pktSysArea {
long serialNo;
long parentNo;
long currentStep;
long currentThread;
long priority;
long errorNo;
long errorThread;
long timeOut;
};
typedef struct tag<パケット名1>D {
<型1> <変数1>;
<型2> <変数2>;
・
・
} <パケット名1>DATA;
typedef struct tag<パケット名1>T {
long code[<コードサイズ>];
char constArea[<サイズ>];
struct pktSysArea sys;
<パケット名1>DATA d;
} <パケット名1>TBL;
//}}PKT_TBL
以下 <パケット名2> 以降に関する構造体が続く
・
・
#endif // !defined(PKTTBL_H__INCLUDED_)
◇
パケットサイズ定義ファイル pkttbl.cpp
// pkttbl.cpp
// this file is generated by program
// don't edit
#include "..\<パス名>\pkttbl.h"
char tbl_createtime[]=GENERATE_TIME;
int pkt_id_size[][2] = {
{ <パケット名1> , sizeof(<パケット名1>TBL)
},
{ <パケット名2> , sizeof(<パケット名2>TBL)
},
・
・
{ 0
, 0 }
};
◇
スレッドID定義ファイル threaddef.h
プロジェクト管理ファイルに定義されたスレッド名、IDと同じものが#define
に出力される。
// threaddef.h
// this file is generated by program
// don't edit
#if !defined(THREADDEF_H__INCLUDED_)
#define THREADDEF_H__INCLUDED_
#define <スレッド名1> <id1>
#define <スレッド名2> <id2>
・
・
#endif // !defined(THREADDEF_H__INCLUDED_)
◇
スレッドのヘッダ <スレッド名>.h
新規に生成される内容
#if !defined(<スレッド名>_H__INCLUDED_)
#define <スレッド名>_H__INCLUDED_
#include "PktCtrl.h"
//{{THR_CLASS1
#include "..\<パス名>\pkttbl.h"
#include "..\<パス名>\threaddef.h"
class C<スレッド名> : public CPacketCtrl
{
public:
C<スレッド名>(int thrId) : CPacketCtrl(thrId)
{}
virtual int CallFunc(int index, void *in,
void *out);
int <関数名1>S(<パケット名1>DATA *dt);
int <関数名2>A(<パケット名2>DATA *in,
<パケット名1>DATA *out);
int <関数名3>T(<パケット名3>DATA *dt);
int <関数名4>W(<パケット名4>DATA *dt,
long lparam);
int CreatePKTS(<パケット名5>DATA
*in, <パケット名6>DATA *out);
int PassToS(<パケット名6>DATA
*in, <パケット名5>DATA *out);
・
・
//}}THR_CLASS1
・ ※ ユーザが記述する個所
//{{THR_CLASS2
};
//}}THR_CLASS2
extern C<スレッド名> ctl<スレッド名>;
#endif // !defined(<スレッド名>_H__INCLUDED_)
◇
スレッドのソース <スレッド名>.cpp
#include <vcl.h>
#pragma hdrstop
//{{PKT_INC
#include "<スレッド名>.h"
//}}PKT_INC
C<スレッド名> ctl<スレッド名>(<スレッド名>);
//{{FUNC_CALL
int C<スレッド名>::CallFunc(int index, void *in,
void *out) {
int rc = -1;
switch(index) {
case 0 :
rc = <関数名1>S((<パケット名1>DATA *)in);
break;
case 1 :
rc = <関数名2>A((<パケット名2>DATA *)in,
(<パケット名2>DATA *)out);
break;
case 3 :
rc = <関数名3>T((<パケット名3>DATA *)in);
break;
case 4 :
rc = <関数名4>W((<パケット名4>DATA *)in,
(long)out);
break;
case 5 :
rc = CreatePKTS((<パケット名5>DATA *)in, (<パケット名6>DATA *)out);
break;
case 6 :
rc = PassToS((<パケット名6>DATA *)in, (<パケット名5>DATA *)out);
break;
・
・
}
return rc;
}
//}}FUNC_CALL
//{{FUNC_DEF1 ************************************************************
int C<スレッド名>::<関数名1>S(<パケット名1>DATA
*dt)
{
//}}FUNC_DEF1
・
※ ユーザが記述する部分
・
//{{FUNC_DEF3
}
//}}FUNC_DEF3
//{{FUNC_DEF1 ************************************************************
int C<スレッド名>::<関数名2>A(<パケット名2>DATA
*in, <パケット名2>DATA *out)
{
if(!out) {
//}}FUNC_DEF1
・
※ ユーザが記述する部分
・
//{{FUNC_DEF2
}
else {
//}}FUNC_DEF2
・
※ ユーザが記述する部分
・
//{{FUNC_DEF3
}
}
//}}FUNC_DEF3
//{{FUNC_DEF1 ************************************************************
int C<スレッド名>::<関数名3>T(<パケット名3>DATA
*dt)
{
//}}FUNC_DEF1
・
※ ユーザが記述する部分
・
//{{FUNC_DEF3
}
//}}FUNC_DEF3
//{{FUNC_DEF1 ************************************************************
int C<スレッド名>::<関数名4>W(<パケット名4>DATA
*dt, long lparam)
{
//}}FUNC_DEF1
・
※ ユーザが記述する部分
・
//{{FUNC_DEF3
}
//}}FUNC_DEF3
//{{FUNC_DEF1 ************************************************************
int C<スレッド名>::CreatePKTS(<パケット名5>DATA
*in, <パケット名6>DATA *out);
{
//}}FUNC_DEF1
・
※ ユーザが記述する部分
・
//{{FUNC_DEF3
}
//}}FUNC_DEF3
//{{FUNC_DEF1 ************************************************************
int C<スレッド名>::PassToS(<パケット名6>DATA *in,
<パケット名5>DATA *out)
{
//}}FUNC_DEF1
・
※ ユーザが記述する部分
・
//{{FUNC_DEF3
}
//}}FUNC_DEF3
◇
関数の使用状況リスト funclist.txt
ユーザの編集結果を確認する目的で既存のスレッドのソース及びスクリプトを読み込み関数のリ
ストを表示する。
********** thread id: <id1> <スレッド名1>
******************
<No.>[*] <関数名1> <呼出区分>
<パケット名1> <パケット名2> : <使用状況>
・
・
********** thread id: <id2> <スレッド名2>
******************
<No.>[*] <関数名n> <呼出区分>
<パケット名3> <パケット名4> : <使用状況>
・
・
説明 <No.> ソース内での関数の定義順を示す。関数がスクリプトにのみ有る場合は-1となる。
[*]
特殊な関数 CreatePKT, WaitPKT, PassTo には"*"マークが付く
<呼出区分>
同期:"S", 非同期:"A", 処理起動:"T", 待機:"W"
<パケット名2>
引数が1つの関数の場合は"<NULL>"と表示
<使用状況>
"USED":スクリプト、ソース共に使用、"NOTUSED":スクリプトでは不使用
"NEW": スクリプトで使用、ソースにはまだ追加されていない。
"----":WaitPKT,Wait 関数の場合は常に"----"と表示(ソースには追加されない。)
5.パケットからの関数呼び出し
マルチプロセス・マルチスレッドの機能を有効に利用したアプリケーションの開発を実現するため、
パケットから関数を呼び出して結果を受け取る方法は、以下の4種類の方式が選択できるものとする。
(1) 関数の処理が完了してからパケットの次の命令に移る。
パケットの処理
スレッド
(2) 関数の処理の完了を待たずにパケットの次の命令に移り、後でWait関数により結果を受け取る。
(3) 関数の処理を起動し次の命令に移る。結果は受け取らない。
(4) 状態変化をチェックする。
パラメータDO_WAITを指定して関数を呼び出すとパケットは待機状態となり、スレッドが
WPARA_STATCHGイベントを受け取るたびに、スレッドの関数Func4W()が呼び出される。
Func4W()関数が 0 以外を返すとパケットはアクティブとなり次の命令へ移る。
Func4W()関数のチェック内容はユーザがcppファイルの中で記述する。また、
WPARA_STATCHGイベントは、状態変化の原因となった個所で関数bool
StatusChanged()
を呼び出すことにより発生させる。
パケットから呼び出される関数はスレッドのメンバ関数として生成される。関数名は、スクリプ
トに記述された関数名の後ろに関数タイプ(同期実行;“S”、非同期実行;“A”、処理起動:
“T”、待機:“W”)を付加したものとなる。
(5) 特殊な関数
以下の関数は特殊な処理を実行する。
◇
Wait関数
非同期実行した結果をパケットへ受け取る。
◇
CreatePKT関数、WaitPKT関数、PassTo関数
新規に子パケットを生成する。新しく生成するパケットの名前をパラメータで指定。
結果は親パケットからWaitPKT関数を子パケットからPassTo関数を呼び出すことにより受け取る。
6.スクリプトから呼び出される関数のパラメータと使い方
(1) 同期実行
int C<スレッド名>::<関数名>S(<パケット名>DATA
*dt);
パラメータ dt :パケット名の変数エリアへのポインタ
関数を終了したらスクリプトの次の命令へ移る。
(2) 非同期実行
int C<スレッド名>::<関数名>A(<パケット名>DATA
*in, <パケット名>DATA *out);
パラメータ in :パケット名の変数エリアのコピーへのポインタ
out :パケット名の変数エリアへのポインタまたはNULL
本関数は2回呼び出される。1回目の呼び出しはスクリプトから<関数名>を呼び出した時、
2回目はスクリプトからWait()関数を呼び出した時である。1回目の呼び出しでは
outパラメータ
が NULLであり、in はパケットのコピーを指している。2回目はinパラメータが1回目の呼び出し
のin と同じパケットのコピーを指し、out
がWait()を呼び出したパケットの実体を指している。
1回目の呼び出しでは、スレッドで実行したい時間のかかる処理を記述し、2回目には単に結果
をout へ格納する処理と復帰コードを設定する処理のみを記述する。
1回目のinにパケットの実体が渡されない理由は、パケットを他のスレッドにPostしてから本関
数が呼び出されるためである。
(3) 処理起動
int C<スレッド名>::<関数名>T(<パケット名>DATA
*dt);
パラメータ dt :パケット名の変数エリアのコピーへのポインタ
dt はパケットのコピーへのポインタであり、実体が渡されない理由は非同期実行と同じである。
復帰値に何をセットしても以降の処理に影響は無い。
(4) 待機
int C<スレッド名>::<関数名>W(<パケット名>DATA
*dt, long lparam);
パラメータ dt :パケット名の変数エリアへのポインタ
lparam:補助パラメータ
lparam には本関数がどのような状態で呼び出されたかについての情報がセットされている。最
初にスクリプトから呼び出されるときは
lparmに LPARAM_1STCALL がセットされる。また、
SetThreadTimer()関数により起動したタイマーがタイムアップした時には
LPARAM_TIMER がセッ
トされる。StatusChanged()関数によるイベントを受け取った時にはStatusChanged()関数のパラメ
ータで指定した値がセットされる。StatusChanged()関数のパラメータにはLPARAM_USER
以上の値
を使用するものとする。
本関数の復帰値に0をセットするとそのまま待機し、0以外をセットすると次の命令へ進む。
(5) スクリプトからのパケット生成
int C<スレッド名>::CreatePKTS(<パケット名1>DATA
*in, <パケット名2>DATA *out);
パラメータ in :生成元パケットの変数エリアへのポインタ
out :生成されるパケットの変数エリアへのポインタ
生成する際の初期化を本関数内で記述する。
(6) パケットと生成元パケット間のデータ受け渡し
int C<スレッド名>::PassToS(<パケット名6>DATA
*in, <パケット名5>DATA *out)
パラメータ in :生成されたパケットの変数エリアへのポインタ
out :生成元のパケットの変数エリアへのポインタ
本関数の中でパケットのどの変数からどの変数へデータを渡すかを記述する。
7.パケット処理プログラムメンバ関数
クラス CpacketCtrlのメンバ関数を示す。
型 関数名 パラメータ | 機 能 |
CPacketCtrl(int nId); | コンストラクタ
nId:スレッドまたはウィンドウID |
~CPacketCtrl(); | デストラクタ |
Int
BeginThread(int cycle); |
スレッドの開始
cycle:Polling周期(msec),0を指定すると受動的 なスレッドとなる。 復帰値:0:正常終了,<0:異常終了 |
bool
ExitThread(TForm *mainWin); |
スレッドの終了
MainWin:アプリケーションのメインウインドウを 指定する。 復帰値:true:正常終了,false:異常終了 |
bool
AttachForm(TForm *form); |
ウィンドウのメッセージ処理クラスとして初期化
form:ウィンドウを指定 |
bool
DetachForm(TForm *mainWin); |
ウィンドウのメッセージ処理クラスを終了する。
MainWin:アプリケーションのメインウインドウを 指定する。 |
Virtual bool
OnInitial(); |
スレッド起動直後に呼び出される処理
復帰値:true:正常終了,false:異常終了 |
Virtual bool
OnExit(); |
スレッド終了前に呼び出される処理
復帰値:true:正常終了,false:異常終了 |
Virtual int
OnPktMessage(TMessage &Message); |
ウィンドウへのメッセージを本クラスのイベント処
理へ渡すための関数 復帰値:0 |
Virtual int
Polling(); |
定期的に呼び出される処理
復帰値:0 |
bool
StatusChanged(long lparam); |
同じスレッドで待っている他のパケットに状態変化
通知を送る。 復帰値:true:正常終了,false:異常終了 |
bool
SetPktTimer(void *pData, int interval, int isOneShot); |
タイマーを起動する。DO_WAITパラメータにより呼び
出された関数の中でのみ使用する。 PData:パケットデータへのポインタ Interval:間隔(msec) IsOneShot: ONESHOT_TIMER, CYCLIC_TIMERのい ずれかを指定する。 復帰値:true:正常終了,false:異常終了 |
int
SetThreadTimer(int interval, int isOneShot); |
タイマーを起動する。
Interval:間隔(msec) IsOneShot: ONESHOT_TIMER, CYCLIC_TIMERのい ずれかを指定する。タイムアップすると OnThreadTimer()が呼び出される。 復帰値:タイマーID |
virtual void
OnThreadTimer(int timerId); |
SetThreadTimer()により発生するタイマーイベン
トにより呼び出される。 timerId: SetThreadTimer()の復帰値と同じ値 |
bool
KillThreadTimer(int timerId); |
SetThreadTimer()によりセットしたタイマーを停
止する。 timerId: SetThreadTimer()の復帰値 復帰値:true:正常終了,false:異常終了 |
int
GetSystemData(void *pData, int para);
|
パケットデータへのポインタからシステム変数を取
得する関数 pData: パケットデータ para: ITEM_SERIAL : パケット識別No.取得 ITEM_PARENT : 生成元パケット識別No.取得 ITEM_PRIORITY: 優先度取得 ITEM_ERRORNO : システムエラー発生スレッドID取得 ITEM_ERRTHR : システムエラーNo.取得 ITEM_TIMEOUT : タイムアウト取得 復帰値:システム変数の値 |
void *
EnumWaitingPacket(int pktId, int *nIndex);
|
DO_WAITで呼び出されスレッドのキューで待機状態
のパケットを列挙する。 pktId:0以外:パケットのIDを指定する。 0:スレッドに所有される全ての待機状態 のパケット nIndex:検索用パラメータ 復帰値:パケットへのポインタ |
void
Trace(char *fmt, ...);
|
デバッグツールのMESSAGEウィンドウへデバッ
グメッセージを送る。 デバッグツールが起動していない場合はファイ ル"tracelog.txt"へ書き出す。デバッグツールか らの設定により"tracelog.txt"への出力を停止で きる。
|
型 関数名 パラメータ | 機 能 |
bool FAR PASCAL __export
CreatePacket(int pktId, int thrID); |
パケットを生成してthrIDで指定されたスレッドに
Postする。 |
char *FAR PASCAL __export
AllocPacket(int pktId, struct tPktHeader *parent);
|
パケットのエリアを取得して初期化する。Postしな
い。スレッドがBusyループの処理中にパケットを生 成してPostしたい場合に、本関数により取得したパ ケットのデータエリアのパケット変数へ直接データ をセットして、次のPostPktMessage()と組み合わせ て使用する。 本関数の使用は必要最小限に留めCreatePacket()を 使用することを推奨する。 pktId: パケットID parent: PKTALLOC_NEWを指定 復帰値:確保したパケットへのポインタ NULL:異常終了 |
bool FAR PASCAL __export
PostPktMessage(short nId, UINT msg, WPARAM wParam, LPARAM lParam); |
AllocPacket()で獲得したパケットをPostする。
nId:Post先スレッドID msg:WM_PACKETMSGを指定 wParam:0を指定 lParam: パケットのエリアへのポインタを指定 復帰値:true:正常終了,false:異常終了 |