У меня есть строковая команда, которую я хотел бы выполнить асинхронно при записи на ее вход и чтении ее вывода. Звучит просто, верно, дьявол находится в кросс-платформе. Я нацелен как на 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*
и связанных функций.
Вы не говорите, если вы пишете GUI или консольное приложение. Если последний, popen() работает в Windows. – 2010-01-09 15:47:45