NSTask と std{out,err}
Cocoa アプリケーションで別プログラム(コマンドライン)を動かす時、stdout,stderrの出力を受け取る方法。
Cocoa で別のコマンドラインプログラムを動かそうとすると、NSTask を利用する事になる。このNSTask は BSD (*NIX)で言うfork関数をCocoaに合わした形のクラスになっている。
具体的に言うと、
-(void) setLaunchPath :(NSString *)path -(void) setArguments :(NSArray *)argument -(void) setStandardOutput:(NSPipe*)pipe -(void) setStandardError:(NSPipe*)pipe -(void) launch -(BOOL) isRunning -(int) terminationStatus -(void) waitUntilExit
といった関数がある。
- setLaunchPath
- 実行するプログラムまでのパスを設定する。
- setArguments
- プログラムを実行する時に、プログラムに渡す引数。NSArrayの配列の全ての要素はNSString型でなければならない。
- setStandardOutput
- 引数のNSPipeが、プログラムが『標準出力』で書き出した内容を保持する。
- setStandardError
- 引数のNSPipeが、プログラムの『エラー出力』で書き出した内容を保持する。
- launch
- プログラムを実行する。
- isRunning
- プログラムが実行しているか確認する関数。YESの場合実行しており、NOの場合は実行していない。
- terminationStatus
- プログラムが終了した際のステータス番号。sys/errno.h を参照。
- waitUntilExit
- プログラムが終了するまで待機する関数。
以下、簡単な実行例。
@interface MyWindow : NSWindow { IBOutlet NSTextField *argument; IBOutlet NSTextField *stderrField; IBOutlet NSTextField *stdoutField; } - (IBAction)exec:(id)sender; @end @implementation MyWindow - (IBAction)exec:(id)sender { NSTask *task = [[NSTask alloc] init]; NSPipe *stdoutPipe = [[NSPipe alloc] init]; NSPipe *stderrPipe = [[NSPipe alloc] init]; NSArray *arr = [NSArray arrayWithObjects:[argument stringValue]]; [task setLaunchPath:@"/bin/echo"]; [task setArguments:arr]; [task setStandardOutput:stdoutPipe]; [task setStandardError:stderrPipe]; // Launch the process. [task launch]; [task waitUntilExit]; // End launch process. // Output data setting. NSData *outData = [[stdoutPipe fileHandleForReading] availableData]; NSData *errData = [[stderrPipe fileHandleForReading] availableData]; const char *outChar = (const char*)[outData bytes]; const char *errChar = (const char*)[errData bytes]; NSString *outStr = nil; NSString *errStr = nil; outStr = (outChar) ? [NSString stringWithCString:outChar encoding:NSASCIIStringEncoding] : [NSString string]; errStr = (errChar) ? [NSString stringWithCString:errChar encoding:NSASCIIStringEncoding] : [NSString string]; [stdoutField setStringValue:outStr]; [stderrField setStringValue:errStr]; [task release]; [stdoutPipe release]; [stderrPipe release]; } @end
ところで、Safariとか動かすにはどうするか見事に忘れた・・・orz