5

私は現在、NSTask、NSPipe、NSFileHandle ビジネスの穴に頭を悩ませようとしています。そこで、C コードをコンパイルして実行できる小さなツールを作成しようと考えました。また、stdout と stdin をテキスト ビューにリダイレクトできるようにしたいと考えていました。

これが私がこれまでに得たものです。この投稿のコードを使用して stdio をリダイレクトしました: What is the best way to redirect stdout to NSTextView in Cocoa?

NSPipe *inputPipe = [NSPipe pipe];
// redirect stdin to input pipe file handle
dup2([[inputPipe fileHandleForReading] fileDescriptor], STDIN_FILENO);
// curInputHandle is an instance variable of type NSFileHandle
curInputHandle = [inputPipe fileHandleForWriting];

NSPipe *outputPipe = [NSPipe pipe];
NSFileHandle *readHandle = [outputPipe fileHandleForReading];
[readHandle waitForDataInBackgroundAndNotify];
// redirect stdout to output pipe file handle
dup2([[outputPipe fileHandleForWriting] fileDescriptor], STDOUT_FILENO);

// Instead of writing to curInputHandle here I would like to do it later
// when my C program hits a scanf
[curInputHandle writeData:[@"123" dataUsingEncoding:NSUTF8StringEncoding]];

NSTask *runTask = [[[NSTask alloc] init] autorelease];
[runTask setLaunchPath:target]; // target was declared earlier
[runTask setArguments:[NSArray array]];
[runTask launch];

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(stdoutDataAvailable:) name:NSFileHandleReadCompletionNotification object:readHandle];

そして、ここで stdoutDataAvailable メソッド

- (void)stdoutDataAvailable:(NSNotification *)notification
{
    NSFileHandle *handle = (NSFileHandle *)[notification object];
    NSString *str = [[NSString alloc] initWithData:[handle availableData] encoding:NSUTF8StringEncoding];
    [handle waitForDataInBackgroundAndNotify];
    // consoleView is an NSTextView
    [self.consoleView setString:[[self.consoleView string] stringByAppendingFormat:@"Output:\n%@", str]];
}

このプログラムは問題なく動作しています。stdout をテキスト ビューに出力し、inputPipe から "123" を読み取る C プログラムを実行しています。上記のコメントで示したように、必要に応じてタスクの実行中に入力を提供したいと思います。

というわけで、今質問が2つあります。

  1. 誰かが私のinputPipeからデータを読み取ろうとするとすぐに通知を受け取る方法はありますか?
  2. 1 に対する答えが「いいえ」の場合、別のアプローチを試すことはできますか? NSTask 以外のクラスを使用している可能性がありますか?

ヘルプ、サンプル コード、他のリソースへのリンクは大歓迎です。

4

1 に答える 1

2

の「プル」を検出できるかどうかはわかりませんNSPipeselect()I/O 可用性イベントを使用して、または使用kqueueして、基になるファイル記述子の I/O 可用性イベントを検索することで、書き込み可用性をポーリングするとうまくいくかもしれないという漠然とした感覚がありますNSFileHandleが、この方法でこれらの機能を使用することにあまり慣れていません。

任意の C プログラムをサポートする必要がありますか、それとも特別なデーモンまたは開発したものですか?

独自のプログラムの場合は、 に対するフィードバックのリクエストを監視するか、送信したいものが見つかったときにoutputPipe入力を爆破して、準備ができたら C プログラムにそれを消費させることができます。inputPipeそれが他の誰かのコードである場合は、次の付録 A-4scanf説明されているようなリンク時の方法を使用して (それはあなたがコンパイルしているコードであるため) フックして友達にすることができる場合があります。

http://www.cs.umd.edu/Library/TRs/CS-TR-4585/CS-TR-4585.pdf

その要点は.dylib、カスタム I/O 関数 (アプリに入力が必要であることを示すシジルをアプリに送信する場合があります) を使用して を作成し、それをビルドされたプログラムにリンクしDYLD_BIND_AT_LAUNCH=YES、起動されたタスクの環境変数 ( ) を設定し、それを実行します。これらのフックを取得したら、ホスト プログラムに必要な利便性を提供できます。

于 2011-06-27T19:31:24.777 に答える