Запишите стандартный ввод NSTasks после запуска - PullRequest
5 голосов
/ 15 июня 2011

Я сейчас пытаюсь обернуть голову вокруг дыры 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 Ответ

2 голосов
/ 27 июня 2011

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

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

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

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

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

...