本机C/ c++中衍生过程的标准输入和输出的跨平台重定向(与解决方案一起编辑)

时间:2020-12-08 12:09:55

I have a string command I'd like to execute asynchronously while writing to its input and reading its output. Sounds easy, right, the devil is in the cross-platform. I'm targeting both MSVC/Win32 and gcc/Linux and obviously want to write the minimum amount of platform-specific code. My google-fu has failed me, I get too much noise for my queries, so I started with what I know.

我有一个字符串命令,我希望在写入输入并读取输出时异步执行。听起来很容易,对,魔鬼就在跨平台上。我的目标是MSVC/Win32和gcc/Linux,显然我想编写特定于平台的代码的最小数量。我的google-fu让我失望了,我的查询太吵了,所以我从我所知道的开始。

popen - nice and easy, returns FILE* that is easy to consume everywhere. But here's what MSDN have to say about _popen:

popen -漂亮和容易,返回文件*,这是容易消费的各地。但是对于_popen MSDN有以下几点要说:

If used in a Windows program, the _popen function returns an invalid file pointer that causes the program to stop responding indefinitely. _popen works properly in a console application. To create a Windows application that redirects input and output, see Creating a Child Process with Redirected Input and Output in the Platform SDK.

如果在Windows程序中使用,_popen函数将返回一个无效的文件指针,该指针将导致程序停止无限响应。_popen在控制台应用程序中正常工作。要创建重定向输入和输出的Windows应用程序,请参见在平台SDK中创建带有重定向输入和输出的子进程。

and so popen is out of the question (edit: because I'd like my code to work in GUI application). The Windows way to do it is in my opinion rather ugly and verbose. I could live with platform specific spawn code but I'd want at least the I/O code to be the same. Here, however, I hit a wall between the WinAPI HANDLEs and C FILE*, and int file descriptor. Is there a way to "convert" a HANDLE to FILE* or int fd or vice-versa? (Google failed me once more on this one, all the keywords I tried are way overused)

所以popen是不可能的(编辑:因为我希望我的代码在GUI应用程序中工作)。在我看来,Windows的做法是相当丑陋和冗长的。我可以使用特定于平台的衍生代码,但我希望至少I/O代码是相同的。然而,在这里,我碰到了WinAPI句柄和C文件*以及int文件描述符之间的一堵墙。是否有一种方法可以将句柄“转换”为FILE*或int fd或相反?(谷歌又一次让我失望,我试过的所有关键词都被滥用了)

Is there better way to do the whole thing with little platform-specific code?

是否有更好的方法使用特定于平台的代码来完成整个过程?

External libraries are not out of the question, however dependency maintenance is a pain, especially so on multiple platforms so I'd like to reduce dependencies. I didn't find such library in boost also.

外部库不是不可能的,但是依赖项维护很麻烦,尤其是在多个平台上,所以我想减少依赖项。我也没有在boost中找到这样的库。


Just for the record, what worked for me in the end. On Windows/MSVC, CreatePipe() + CreateProcess() as outlined here, using _open_osfhandle() followed by _fdopen() to get FILE* to the process input and output. On Linux/GCC, nothing new here, creating pipe()s; fork() then dup2() the pipes; exec(); fdopen() on the relevant file descriptors. That way, only the process spawning code is platform dependent (which is ok, as on Windows I'd like to control additional STARTUPINFO parameters), writing input and reading output is done through standard FILE* and related functions.

我想说的是,最终对我起作用的是什么。在Windows/MSVC中,CreatePipe() + CreateProcess()如这里所述,使用_open_osfhandle(),然后是_fdopen(),将文件*获取到流程输入和输出。在Linux/GCC上,没有什么新东西,创建pipe()s;fork()然后dup2()管道;exec();fdopen()用于相关的文件描述符。这样,只有生成代码的过程是依赖于平台的(这是可以的,因为在Windows上我想要控制额外的STARTUPINFO参数),编写输入和读取输出是通过标准文件*和相关函数完成的。

2 个解决方案

#1


2  

for converting windows HANDLEs to C file descriptors use _open_osfhandle http://msdn.microsoft.com/en-us/library/bdts1c9x%28VS.71%29.aspx

为了将windows句柄转换为C文件描述符,请使用_open_osfhandle http://msdn.microsoft.com/en- us/library/bdts1c9x%28vs.7129.aspx。

EDIT: this example once helped me aswell with a similar problem: http://www.halcyon.com/~ast/dload/guicon.htm

编辑:这个例子也帮助我解决了一个类似的问题:http://www.halcyon.com/~ast/dload/guicon.htm

#2


6  

Give libexecstream a whirl. It's cross platform, and allows you to trap the input, output and error streams of a process asynchronously as C++ style streams.

给libexecstream旋转。它是跨平台的,允许您将流程的输入、输出和错误流异步捕获为c++样式的流。

I've used it on Linux, Darwin and Windows and it seems to work. It's also pretty lightweight so integrates into projects with little pain, and has a pretty open BSD licence. I don't think there's any way around using a library (other than writing your own variations for each platform).

我曾在Linux、Darwin和Windows上使用过它,它似乎很有用。它也是相当轻量的,因此可以轻松地集成到项目中,并且具有相当开放的BSD许可证。我认为没有任何方法可以使用一个库(除了为每个平台编写自己的变体)。

#1


2  

for converting windows HANDLEs to C file descriptors use _open_osfhandle http://msdn.microsoft.com/en-us/library/bdts1c9x%28VS.71%29.aspx

为了将windows句柄转换为C文件描述符,请使用_open_osfhandle http://msdn.microsoft.com/en- us/library/bdts1c9x%28vs.7129.aspx。

EDIT: this example once helped me aswell with a similar problem: http://www.halcyon.com/~ast/dload/guicon.htm

编辑:这个例子也帮助我解决了一个类似的问题:http://www.halcyon.com/~ast/dload/guicon.htm

#2


6  

Give libexecstream a whirl. It's cross platform, and allows you to trap the input, output and error streams of a process asynchronously as C++ style streams.

给libexecstream旋转。它是跨平台的,允许您将流程的输入、输出和错误流异步捕获为c++样式的流。

I've used it on Linux, Darwin and Windows and it seems to work. It's also pretty lightweight so integrates into projects with little pain, and has a pretty open BSD licence. I don't think there's any way around using a library (other than writing your own variations for each platform).

我曾在Linux、Darwin和Windows上使用过它,它似乎很有用。它也是相当轻量的,因此可以轻松地集成到项目中,并且具有相当开放的BSD许可证。我认为没有任何方法可以使用一个库(除了为每个平台编写自己的变体)。