gpt4 book ai didi

c++ - Python中低级标准输入的重复重定向

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:55:32 25 4
gpt4 key购买 nike

这是我的情况:有一些旧的 C++ 代码,我正试图为其创建一个简单的 Python 包装器。此代码最初设计为从命令行驱动,并期望将输入文件通过管道传输到其中。为了尽量减少对这段代码的干扰,我将 main 函数转换为普通的 extern "C"函数,并将其编译成一个共享库,我将其加载到 Python 中并通过 ctypes 驱动。请注意,我不想通过系统调用来驱动此代码,因为它最终将在集群上运行并执行无数次。

从这里开始,我需要控制较低级别的标准输入,以便设置输入文件,以便可以通过 C++ 代码中的各种“cin”语句读取它。

从我目前所学的情况来看,理论上我似乎可以通过使用 os 库覆盖标准输入文件描述符来做到这一点。我编写了以下示例,它似乎在 Python 中运行良好(基于此线程中的各种信息:Python version of freopen()):

import os
import sys

def freopen(f,option,stream):
oldf = open(f,option)
oldfd = oldf.fileno()
newfd = stream.fileno()
os.close(newfd)
os.dup2(oldfd, newfd)

# Original stdout file descriptor:
fd = sys.stdout.fileno()
orig_stream = os.fdopen(os.dup(fd), 'w')

# Test writing to file:
freopen("hello","w",sys.stdout)
print "world"
sys.stdout.flush()
freopen("hello2","w",sys.stdout)
print "world2"
sys.stdout.flush()

# Restore stdout to normal
os.dup2(orig_stream.fileno(),sys.stdout.fileno())

print "back to normal!"

# Test reading:
freopen("hello","r",sys.stdin)
print sys.stdin.readlines()

freopen("hello2","r",sys.stdin)
print sys.stdin.readlines()

这会产生输出

back to normal!
['world\n']
['world2\n']

(以及两个文件“hello”和“hello2”)对我来说。很好!不幸的是,当我的 C++ 库函数正在读取标准输入流时,它似乎不起作用。奇怪的是,第一次运行正常,但第二次就失败了;没有错误发生,看起来更像是标准输入流对于第二次重定向来说只是空的。当我重定向 stdout 而不是 stdin 时,它似乎工作正常。

我需要做些什么来为第二遍重置较低级别的标准输入流吗?

额外信息:在 C++ 方面,stdin 只是像这样读取:

while (getline(cin,line)) {
// do stuff with line...

此外,如果解决方案是“仅限 Linux”,我也不太担心。

编辑:我正在运行 Python 2.7.1

更新:嗯,也许库代码做了一些奇怪的事情,因为如果我将测试代码的“阅读测试”部分更改为:

# Test reading:
freopen("hello","r",sys.stdin)
os.system("cat")

freopen("hello2","r",sys.stdin)
os.system("cat")

然后是预期的输出

back to normal!
world
world2

仍在制作中。因此,无论“cat”如何对待标准输入,它似乎都与这种标准输入重定向方法完全兼容。唔。当然,通过此方法创建了一个新的“cat”进程,并且每次都将新的 stdin 连接到它,所以它与调用我的库函数并不完全相同。我将尝试创建一个最小的库函数来重现问题...

最佳答案

啊哈!事实证明,这个问题很有帮助:cin.ignore() and cin.clear() in C++

所以看起来至少在 C++ 中,当流到达 eof 时,它会将各种错误标志设置为 true ( http://www.cplusplus.com/reference/ios/ios/good/ )。这可以防止对流执行进一步的操作。当我的库代码是一个独立的可执行文件时,这种行为很好,因为该程序只会尝试从 cin 读取文件一次。但是,将代码转换为库后,当我的循环返回到第二次调用库函数时,库函数仍在处理相同的标准输入流。流仍然设置了错误标志,因此 cin 读取在第二次传递时失败。

为了解决问题,我添加了

std::cin.clear();

到库代码,在尝试 cin 读取之前。这会重置流的错误标志,然后可以正常读取。

我不确定这种流标志的重置是否可以在 Python 端处理;很高兴知道这一点。

关于c++ - Python中低级标准输入的重复重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20000332/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com