Кроссплатформенное перенаправление стандартного ввода и вывода порожденного процесса на родном C / C ++ (редактирование с решением)
У меня есть строковая команда, которую я хотел бы выполнить асинхронно при записи на вход и чтении на выходе. Звучит легко, верно, дьявол в кроссплатформенности. Я ориентируюсь как на MSVC / Win32, так и на gcc / Linux и, очевидно, хочу написать минимальный объем кода для конкретной платформы. Мой гугл-фу подвел меня, я получаю слишком много шума для своих запросов, поэтому я начал с того, что знаю.
POPEN - красиво и легко, возвращает FILE *, который легко использовать везде. Но вот чтоMSDN должен сказать о _popen:
При использовании в программе Windows функция _popen возвращает недопустимый указатель файла, из-за которого программа перестает отвечать на запросы неопределенно долго. _popen работает правильно в консольном приложении. Чтобы создать приложение Windows, которое перенаправляет ввод и вывод, см. Создание дочернего процесса с перенаправленным вводом и выводом в SDK платформы.
и поэтому о popen не может быть и речи (правка: потому что я хотел бы, чтобы мой код работал в приложении с графическим интерфейсом). Способ Windows сделать это, на мой взгляд, довольно уродлив и многословен. Я мог бы жить с порождающим кодом для конкретной платформы, но я бы хотел, чтобы хотя бы код ввода-вывода был таким же. Здесь, однако, я ударил стену между WinAPIHANDLE
с и сFILE*
, а такжеint
дескриптор файла. Есть ли способ "конвертировать"HANDLE
вFILE*
или жеint
фд или наоборот? (Google снова подвел меня в этом вопросе, все ключевые слова, которые я пробовал, слишком часто)
Есть ли лучший способ сделать все это с небольшим кодом для конкретной платформы?
О внешних библиотеках не может быть и речи, однако обслуживание зависимостей является проблемой, особенно на нескольких платформах, поэтому я хотел бы уменьшить зависимости. Я не нашел такую библиотеку и в boost.
Просто для записи, что сработало для меня в конце концов. В Windows / MSVC,CreatePipe()
+ CreateProcess()
как изложеноВот, с помощью_open_osfhandle()
с последующим_fdopen()
получитьFILE*
к процессу ввода и вывода. На Linux / GCC, ничего нового здесь, созданиеpipe()
s;fork()
тогдаdup2()
трубы;exec()
; fdopen()
на соответствующих файловых дескрипторов. Таким образом, только процессный код процесса зависит от платформы (это нормально, так как в Windows я хотел бы контролировать дополнительныеSTARTUPINFO
параметры), запись ввода и чтение вывода осуществляется через стандартныйFILE*
и связанные функции.