我尝试使用" _popen()"来编译函数。使用CodeBlocks / MinGW C ++编译器。但是,编译器无法定位该函数。我grep stdio.h头文件,找到" _popen"但是,由于ifdef的定义,它没有被选中。如何设置编译,以便它可以使用CodeBlocks编译器编译_popen,_wpopen,popen或wpopen或类似的东西?
以下是在CodeBlocks下无法编译的代码示例:
#include <cstdio>
#include <cstdlib>
#include <deque>
using namespace std;
// System(cmd) and capture output of command
int SystemCapture(string cmd, deque<string>& cmdout, int& RetCode )
{
RetCode = 0;
FILE* Pipe = _popen(cmd.c_str(), "rt" );
if(!Pipe)
return -1;
char Buffer[128];
while(fgets(Buffer, 128, Pipe)) {
cmdout.push_back(Buffer);
}
if (feof(Pipe)) {
RetCode =_pclose(Pipe);
return 0;
}
return -2;
}
我不知道它是否有任何区别,但我的编译器标志启用了c ++ 11。
错误消息显示为_popen的原型未在头文件&#34; stdio.h&#34;中定义。但是,Microsoft文档声明这是_popen()所在的位置。这是来自Codeblocks的错误消息:
BUILD.LOG TAB的错误消息:
mingw32-g++.exe -Wall -fexceptions -g -std=c++11 -g
-c MyCode.cpp -o obj\Debug\MyCode.o
MyCode.cpp:270:42: error: '_popen' was not declared in this scope
FILE* Pipe = _popen(cmd.c_str(), "rt" );
^
MyCode.cpp:281:27: error: '_pclose' was not declared in this scope
RetCode =_pclose(Pipe);
^
Process terminated with status 1 (0 minute(s), 1 second(s))
2 error(s), 0 warning(s) (0 minute(s), 1 second(s))
我尝试在#include:
下添加我自己的原型FILE* _popen (const char*, const char*);
int _pclose (FILE*);
然后编译器的链接阶段失败:
undefined reference to _popen(char const*, char const*)
undefined reference to _pclose(_iobuf*)
我尝试将popen重命名为以下变体: popen,_popen,_wpopen,wpopen
也没有幸运。
然而,如果我grep stdio.h我看到ifdef围绕着popen原型...
答案 0 :(得分:0)
我无法弄清楚Codeblocks / MinGW的popen / pclose问题。所以我通过使用CreateProcess()和CreatePipe()来解决这个问题。这是对我有用的解决方案:
//C++11
#include <cstdio>
#include <iostream>
#include <windows.h>
#include <cstdint>
#include <deque>
#include <string>
#include <thread>
using namespace std;
int SystemCapture(
string CmdLine, //Command Line
string CmdRunDir, //set to '.' for current directory
string& ListStdOut, //Return List of StdOut
string& ListStdErr, //Return List of StdErr
uint32_t& RetCode) //Return Exit Code
{
int Success;
SECURITY_ATTRIBUTES security_attributes;
HANDLE stdout_rd = INVALID_HANDLE_VALUE;
HANDLE stdout_wr = INVALID_HANDLE_VALUE;
HANDLE stderr_rd = INVALID_HANDLE_VALUE;
HANDLE stderr_wr = INVALID_HANDLE_VALUE;
PROCESS_INFORMATION process_info;
STARTUPINFO startup_info;
thread stdout_thread;
thread stderr_thread;
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = nullptr;
if (!CreatePipe(&stdout_rd, &stdout_wr, &security_attributes, 0) ||
!SetHandleInformation(stdout_rd, HANDLE_FLAG_INHERIT, 0)) {
return -1;
}
if (!CreatePipe(&stderr_rd, &stderr_wr, &security_attributes, 0) ||
!SetHandleInformation(stderr_rd, HANDLE_FLAG_INHERIT, 0)) {
if (stdout_rd != INVALID_HANDLE_VALUE) CloseHandle(stdout_rd);
if (stdout_wr != INVALID_HANDLE_VALUE) CloseHandle(stdout_wr);
return -2;
}
ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));
ZeroMemory(&startup_info, sizeof(STARTUPINFO));
startup_info.cb = sizeof(STARTUPINFO);
startup_info.hStdInput = 0;
startup_info.hStdOutput = stdout_wr;
startup_info.hStdError = stderr_wr;
if(stdout_rd || stderr_rd)
startup_info.dwFlags |= STARTF_USESTDHANDLES;
// Make a copy because CreateProcess needs to modify string buffer
char CmdLineStr[MAX_PATH];
strncpy(CmdLineStr, CmdLine.c_str(), MAX_PATH);
CmdLineStr[MAX_PATH-1] = 0;
Success = CreateProcess(
nullptr,
CmdLineStr,
nullptr,
nullptr,
TRUE,
0,
nullptr,
CmdRunDir.c_str(),
&startup_info,
&process_info
);
CloseHandle(stdout_wr);
CloseHandle(stderr_wr);
if(!Success) {
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
CloseHandle(stdout_rd);
CloseHandle(stderr_rd);
return -4;
}
else {
CloseHandle(process_info.hThread);
}
if(stdout_rd) {
stdout_thread=thread([&]() {
DWORD n;
const size_t bufsize = 1000;
char buffer [bufsize];
for(;;) {
n = 0;
int Success = ReadFile(
stdout_rd,
buffer,
(DWORD)bufsize,
&n,
nullptr
);
printf("STDERR: Success:%d n:%d\n", Success, (int)n);
if(!Success || n == 0)
break;
string s(buffer, n);
printf("STDOUT:(%s)\n", s.c_str());
ListStdOut += s;
}
printf("STDOUT:BREAK!\n");
});
}
if(stderr_rd) {
stderr_thread=thread([&]() {
DWORD n;
const size_t bufsize = 1000;
char buffer [bufsize];
for(;;) {
n = 0;
int Success = ReadFile(
stderr_rd,
buffer,
(DWORD)bufsize,
&n,
nullptr
);
printf("STDERR: Success:%d n:%d\n", Success, (int)n);
if(!Success || n == 0)
break;
string s(buffer, n);
printf("STDERR:(%s)\n", s.c_str());
ListStdOut += s;
}
printf("STDERR:BREAK!\n");
});
}
WaitForSingleObject(process_info.hProcess, INFINITE);
if(!GetExitCodeProcess(process_info.hProcess, (DWORD*) &RetCode))
RetCode = -1;
CloseHandle(process_info.hProcess);
if(stdout_thread.joinable())
stdout_thread.join();
if(stderr_thread.joinable())
stderr_thread.join();
CloseHandle(stdout_rd);
CloseHandle(stderr_rd);
return 0;
}
int main()
{
int rc;
uint32_t RetCode;
string ListStdOut;
string ListStdErr;
cout << "STARTING.\n";
rc = SystemCapture(
"C:\\Windows\\System32\\ipconfig.exe", //Command Line
".", //CmdRunDir
ListStdOut, //Return List of StdOut
ListStdErr, //Return List of StdErr
RetCode //Return Exit Code
);
if (rc < 0) {
cout << "ERROR: SystemCapture\n";
}
cout << "STDOUT:\n";
cout << ListStdOut;
cout << "STDERR:\n";
cout << ListStdErr;
cout << "Finished.\n";
cout << "Press Enter to Continue";
cin.ignore();
return 0;
}
现在你可以理解为什么我担心popen不能在Codeblocks中工作。