2010-01-09 1 views
8

У меня есть строковая команда, которую я хотел бы выполнить асинхронно при записи на ее вход и чтении ее вывода. Звучит просто, верно, дьявол находится в кросс-платформе. Я нацелен как на MSVC/Win32, так и на gcc/Linux и, очевидно, хочу записать минимальное количество кода для конкретной платформы. Мой google-fu подвел меня, я получил слишком много шума для своих запросов, поэтому начал с того, что знаю.Кросс-платформенная переадресация стандартного ввода и вывода порожденного процесса в C/C++ (редактирование с помощью решения)

popen - красивый и легкий, возвращает FILE *, который легко потреблять везде. Но вот что MSDN have to say about _popen:

Если в программе используется ОС Windows, функция _popen возвращает недействительный указатель на файл, который вызывает программу перестает отвечать на запросы на неопределенный срок. _popen работает правильно в консольном приложении. Чтобы создать приложение Windows , которое перенаправляет ввод и вывод , см. Раздел Создание дочернего процесса с перенаправленным вводом и выводом в Платформа SDK.

и поэтому ничего не может поменять (отредактируйте: потому что я хочу, чтобы мой код работал в приложении GUI). Способ Windows это сделать, на мой взгляд, довольно уродливо и многословно. Я мог бы жить с конкретным кодом, созданным на платформе, но я бы хотел, чтобы хотя бы код ввода-вывода был таким же. Здесь, однако, я ударил стену между WinAPI HANDLE и C FILE* и int файловым дескриптором. Есть ли способ «конвертировать» HANDLE в FILE* или int fd или наоборот? (Google снова провалил меня на этом, все ключевые слова, которые я пробовал, были чрезмерно использованы)

Есть ли лучший способ сделать все это с небольшим кодом для конкретной платформы?

Внешние библиотеки не могут быть и речи, однако обслуживание зависимостей - это боль, особенно на разных платформах, поэтому я хотел бы уменьшить зависимости. Я тоже не нашел такую ​​библиотеку в boost.


Просто для записи, что сработало для меня в конце. В Windows/MSVC, CreatePipe() + CreateProcess(), как указано here, используя _open_osfhandle(), а затем _fdopen(), чтобы получить FILE* для ввода и вывода процесса. В Linux/GCC ничего нового здесь нет, создавая pipe() s; fork() затем dup2() трубы; exec(); fdopen() в соответствующих дескрипторах файлов. Таким образом, только код нереста процесса зависит от платформы (это нормально, так как в Windows я хотел бы управлять дополнительными параметрами STARTUPINFO), запись ввода и считывания производится с помощью стандарта FILE* и связанных функций.

+0

Вы не говорите, если вы пишете GUI или консольное приложение. Если последний, popen() работает в Windows. – 2010-01-09 15:47:45

ответ

6

Дать libexecstream вихрь. Это кросс-платформа и позволяет вам асинхронно захватывать поток ввода, вывода и ошибок процесса как потоки стилей C++.

Я использовал его в Linux, Darwin и Windows и, похоже, работает. Он также довольно легкий, поэтому интегрируется в проекты с небольшой болью и имеет довольно открытую лицензию BSD. Я не думаю, что есть какой-либо способ использования библиотеки (кроме написания собственных вариантов для каждой платформы).

Смежные вопросы