Записать в стандартный ввод NSTasks после запуска

В настоящее время я пытаюсь обернуть голову вокруг дырки NSTask, NSPipe, NSFileHandle business. Поэтому я подумал написать небольшой инструмент, который может компилировать и запускать код на Си. Я также хотел иметь возможность перенаправить мой стандартный вывод и стандартный ввод в текстовое представление.

Вот что я получил до сих пор. Я использовал код из этого поста для перенаправления моего stdio: Каков наилучший способ перенаправить стандартный вывод в NSTextView в Какао?

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]];
}

Эта программа работает просто отлично. Он запускает программу C, которая выводит стандартный вывод в мое текстовое представление и читает "123" из моего inputPipe. Как указано в моем комментарии выше, я хотел бы предоставить входные данные, когда задача выполняется, когда это необходимо.

Итак, сейчас есть два вопроса.

  1. Есть ли способ получить уведомление, как только кто-то попытается прочитать данные из моего inputPipe?
  2. Если ответ на 1 - нет, могу ли я попробовать другой подход? Может быть, используя класс, отличный от NSTask?

Любая помощь, пример кода, ссылки на другие ресурсы высоко ценятся!

1 ответ

Я не уверен, что вы можете обнаружить "тянуть" на NSPipe, У меня есть смутное ощущение, что опрос для доступности записи с select() или используя kqueue искать события доступности ввода / вывода в базовом файловом дескрипторе вашего NSFileHandle может сделать свое дело, но я не очень знаком с использованием этих средств таким образом.

Вы должны поддерживать произвольные программы на C, или это специальный демон или что-то, что вы разработали?

Если это ваша собственная программа, вы можете отслеживать запросы на обратную связь outputPipeили просто взорвать ввод на inputPipe когда вы узнаете, что именно вы хотите отправить, и дайте программе на C потреблять ее, когда она будет готова; если это чужой код, вы можете подключить scanf и друзья, использующие метод времени компоновки (так как это код, который вы компилируете), как описано в Приложении A-4:

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

Суть в том, чтобы сделать .dylib с вашими пользовательскими функциями ввода / вывода (которые могут отправлять некоторые символы в ваше приложение, указывающие, что они нуждаются в вводе), связать это со встроенной программой, установить переменную среды (DYLD_BIND_AT_LAUNCH=YES) для запущенного задания и запустите его. Получив эти хуки, вы можете предоставить любые удобства, которые вы хотите для своей хост-программы.

Другие вопросы по тегам