У меня есть строковая команда, которую я хотел бы выполнить асинхронно при записи на вход и чтении ее вывода. Звучит легко, верно, дьявол в кроссплатформенности. Я ориентируюсь как на 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*
и связанных функций.