Кроссплатформенное перенаправление стандартного ввода и вывода порожденного процесса на родном C / C ++ (редактирование с решением) - PullRequest
8 голосов
/ 09 января 2010

У меня есть строковая команда, которую я хотел бы выполнить асинхронно при записи на вход и чтении ее вывода. Звучит легко, верно, дьявол в кроссплатформенности. Я ориентируюсь как на MSVC / Win32, так и на gcc / Linux и, очевидно, хочу написать минимальный объем кода для конкретной платформы. Мой гугл-фу подвел меня, я получаю слишком много шума для своих запросов, поэтому я начал с того, что знаю.

popen - красиво и легко, возвращает FILE *, который легко использовать везде. Но вот что MSDN должен сказать о _popen :

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

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

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

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


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

Ответы [ 2 ]

6 голосов
/ 09 января 2010

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

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

2 голосов
/ 09 января 2010

для преобразования окон HANDLE с в дескрипторы файлов C используйте _open_osfhandle http://msdn.microsoft.com/en-us/library/bdts1c9x%28VS.71%29.aspx

РЕДАКТИРОВАТЬ: этот пример однажды помог мне с аналогичной проблемой: http://www.halcyon.com/~ast/dload/guicon.htm

...