使用 pipe() 和 fdopen() 将数据从 Python 脚本传递到 Windows 中的C++应用程序

Use pipe() and fdopen() to pass data from Python script to C++ application in Windows

本文关键字:Windows C++ 应用程序 脚本 中的 pipe fdopen 使用 数据 Python      更新时间:2023-10-16

我们有一些Linux/macOS应用程序,它可以通过传递文件描述符并从中读取数据来与外部世界进行通信。通常这样做是为了传递stdin/stdout描述符,但是我们使用pipe(),这工作得很好。除了MinGW/Windows。 在Windows下执行相同工作的推荐方法是什么?传递整个文件句柄,或者有模拟类似小整数的描述符的好方法?

在Windows中,C文件描述符在保留字段中STARTUPINFO记录的过程中继承cbReserved2lpReserved2。该协议未记录,但源代码与Visual C++一起分发。使用此功能的 C 函数包括_[w]spawn系列函数和[_w]system。(但是,[_w]system函数在这方面通常没有用,因为只有直接的 cmd.exe 进程继承父级的文件描述符。CMD 不会将它们传递给子进程。

在 Python 2.7 中,os.pipe是通过调用CreatePipe来实现的,它返回管道读写端的不可继承文件句柄。然后通过_open_osfhandle用可继承的文件描述符手动包装这些句柄,但底层操作系统句柄仍然是不可继承的。若要解决此问题,请通过os.dup复制文件描述符,这会在内部复制可继承的文件句柄,然后关闭源文件描述符。例如:

pread, pwrite = os.pipe()
pwrite_child = os.dup(pwrite)
os.close(pwrite)

Python 的subprocess模块通常是创建子进程的首选方法。但是,在这种情况下我们不能使用subprocess,因为它不支持通过STARTUPINFO(*) 继承文件描述符。下面是一个改用os.spawnv的示例:

rc = os.spawnv(os.P_WAIT, 'path/to/spam.exe', ['spam', 'arg1', 'arg2'])

(*) Windows Python 内部使用 C 运行时文件 API 是一个尴尬的情况(例如_wopen_read_write),但在某些地方不支持C文件描述符。它应该咬紧牙关,直接将Windows文件API与操作系统文件句柄一起使用,那么它至少是一致的。