在C ++中从管道获取Gnuplot版本

时间:2016-01-04 18:32:27

标签: c++ gnuplot

在我的C ++程序中(在linux中),我可以打开一个管道来编写和设置Gnuplot程序的值。

FILE *pipe = NULL;

#ifdef WIN32
    pipe = _popen("pgnuplot -persist", "w");
#else
    pipe = popen("gnuplot", "w");
#endif

if(pipe == NULL)
    error("Could not open pipe for write!");

// set title name
fprintf(pipe, "set title 'Sample Points' \n");

现在我需要获得Gnuplot版本。 show version命令执行此操作,但我如何发送此命令然后读取值。打开一个读取管道对我来说似乎不起作用,代码卡在while循环中而没有得到任何数据。

FILE* pipe = popen(command, "r");
if (!pipe)
{
    std::cout << "failed! (can not open pipe)" << endl;
    return;
}

char buffer[128];
std::string result = "";
while(!feof(pipe))
{
    if(fgets(buffer, 128, pipe) != NULL)
        result += buffer;
}
pclose(pipe);

1 个答案:

答案 0 :(得分:2)

因为在我的Debian / Linux / Sid / x86-64上,命令gnuplot --version输出到stdout以下行:

 gnuplot 5.0 patchlevel 1

我只是推荐

FILE* pipversion = popen("gnuplot --version", "r");
if (!pipversion) { perror("popen gnuplot"); exit(EXIT_FAILURE); };
char lineversion[128];
memset (lineversion, 0, sizeof(lineversion));
if (!fgets(lineversion, sizeof(lineversion), pipversion) { 
    perror("fgets"); exit(EXIT_FAILURE);
}
/// lineversion is like: gnuplot 5.0 patchlevel 1
int majvers=0, minvers=0, pos= -1;
char* restvers = NULL;
if (sscanf(lineversion, "gnuplot %d.%d %n", &majvers, &minvers, &pos) >= 2) {
  assert (pos>=0);
  restvers = lineversion+pos;
};
pclose(pipversion);
pipversion = NULL;

之后,majvers包含gnuplot的主要版本(例如,在我的情况下为5),minvers包含次要版本(例如0),restvers为后缀字符串(例如"patchlevel 1"没有引号)。

gnuplot与下一个popen之间更新pipe = popen("gnuplot", "w");的不寻常且不太可能的情况下可能存在潜在竞争条件。 BTW,命名变量pipe的味道很差,因为POSIX和Linux有pipe(2)系统调用。但我不认为值得关注这种竞争条件。

顺便说一下,你很可能想要用pipe(2)的明确的调用替换你的第二个pipe = popen("gnuplot", "w");(后面是适当的fork(2)&amp; {{3 }}}将输入和输出管道都放到gnuplot,并在你自己的execvp(3)中管理它们(可能在event loop左右......见poll(2)&amp; this答案)。

(如果您的应用程序拥有或使用自己的事件循环,特别是如果它是一个高于Qt或GTK的GUI应用程序,您希望对管道使用相同的事件循环;详细信息特定于库提供该事件循环:that&amp; g_spawn_async_with_pipes代表GTK,g_source_add_unix_fd代表Qt ......)

我没有时间详细说明如何做到这一点(双重管道进入命令+事件循环),但QProcess书(在线提供)有几个章节。请注意,您需要某些事件循环。