【问题标题】:Capturing syscall stdout without writing to file in C/C++捕获系统调用标准输出而不用 C/C++ 写入文件
【发布时间】:2010-11-09 08:05:48
【问题描述】:

我想将系统调用的标准输出读入 C/C++ 字符串。我可以在不使用临时文件的情况下执行此操作吗?

Perl

//without file io
$output = `echo hello`;

C++

//with file io
system ("echo hello > tmp");
std::fstream file ("tmp");
std::string s;
file >> s;

【问题讨论】:

  • 这里的问题当然是“系统调用”和“system() 调用”是不一样的。
  • @alex vasi:感谢您的链接,我进行了搜索,但在发布问题之前没有找到该页面。

标签: c++ c system-calls


【解决方案1】:

使用C的popen(可能是最简单的解决方案,即使它不使用C++的iostream):

FILE *p = popen("echo hello", "r");
std::string s;
for (size_t count; (count = fread(buf, 1, sizeof(buf), p));)
    s += string(buf, buf + count);
pclose(p);

假设您的 iostream 具有非标准的 xfstream::xfstream(int fd) 构造函数:

FILE *p = popen("echo hello", "r");
std::ifstream p2(fileno(p));
std::string s;
p2 >> s;
p2.close();
pclose(p);

使用Boost.Iostreams,您不必依赖iostream 的非标准扩展:

boost::iostreams::file_descriptor_source p2(fileno(p));

不幸的是,Windows 很糟糕,_popen 仅适用于控制台应用程序;对于图形应用程序:

SECURITY_ATTRIBUTES sec;
sec.nLength = sizeof(sec);
sec.bInheritHandle = TRUE;
sec.lpSecurityDescriptor = NULL;
HANDLE *h[2];
CreatePipe(&h[0], &h[1], &sec, 0);
SetHandleInformation(h[0], HANDLE_FLAG_INHERIT, 0)
STARTUPINFO si;
memset((void *)&si, 0, sizeof(si));
si.hStdInput = INVALID_HANDLE_VALUE;
si.hStdOutput = h[1];
si.hStdError = INVALUD_HANDLE_VALUE;
si.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, "cmd /c \"echo hello\"", NULL, NULL, TRUE, 0, NULL, NULL, &si, NULL);
boost::iostreams::file_descriptor_source p(h[0]);

(完全未经测试)

【讨论】:

  • 等等...你在同一个流上调用 p2.close() 然后 pclose() 。这意味着你试图关闭它两次。在我看来,一旦你将它传递给 ifstream,你就会失去对该流的控制,并且你不能再使用 p。
【解决方案2】:

This 可能会帮助您从系统调用重定向标准输出。

【讨论】:

    猜你喜欢
    • 2016-04-21
    • 1970-01-01
    • 2023-03-08
    • 2023-03-05
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    相关资源
    最近更新 更多