[英]Get Gnuplot version from pipe in C++
In my C++ program (in linux), I can open a pipe for writing and set values for Gnuplot program. 在我的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");
Now I need to get the Gnuplot version. 现在,我需要获取Gnuplot版本。 The
show version
command does this but how I can send this command and then read the value. show version
命令可以执行此操作,但是如何发送此命令然后读取值。 Opening a pipe for reading seems to not work for me and the code stuck in the while loop without getting any data. 对于我来说,打开管道进行读取似乎不起作用,并且代码陷入了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);
Since on my Debian/Linux/Sid/x86-64 the command gnuplot --version
is outputting to stdout
the following line: 由于在我的Debian / Linux / Sid / x86-64上,命令
gnuplot --version
输出到stdout
的以下行:
gnuplot 5.0 patchlevel 1
I would simply recommend 我只是推荐
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;
After that, majvers
contains the major version of gnuplot
(eg 5 in my case) and minvers
contains the minor version (eg 0), with restvers
being a suffix string (eg "patchlevel 1"
without the quotes). 之后,
majvers
包含gnuplot
的主版本(例如,在我的情况下为5), minvers
包含次版本(例如0), restvers
部分为后缀字符串(例如, "patchlevel 1"
不带引号)。
There might be a potential race condition in the unusual and unlikely case that gnuplot
is updated between this popen
and the next one pipe = popen("gnuplot", "w");
在这种罕见的情况下,在该
popen
和下一个pipe = popen("gnuplot", "w");
之间更新gnuplot
可能存在潜在的竞争条件pipe = popen("gnuplot", "w");
. 。 BTW, naming a variable
pipe
is poor taste, since POSIX and Linux have the pipe(2) system call. 顺便说一句,由于POSIX和Linux具有pipe(2)系统调用,因此命名可变
pipe
的味道很差。 But I don't think it is worth caring about that race condition. 但是我不认为应该关注那种比赛条件。
BTW, you very probably want to replace your second pipe = popen("gnuplot", "w");
顺便说一句,您很可能要替换第二个
pipe = popen("gnuplot", "w");
with an explicit double invocation of pipe(2) (followed by appropriate fork(2) & execvp(3) ...) to have both input and output pipes to gnuplot
, and manage them in your own event loop (probably around poll(2) ... see this & that answers). 通过显式两次调用pipe(2) (后接适当的fork(2)和execvp(3) ...)使输入和输出管道都到达
gnuplot
,并在您自己的事件循环中对其进行管理(可能在poll( 2) ...看到这个和那个答案)。
(if you application has or uses its own event loop, in particular if it is a GUI application above Qt or GTK, you want to use the same event loop for the pipes; details are specific to the library providing that event loop: g_spawn_async_with_pipes & g_source_add_unix_fd for GTK, QProcess for Qt ... ) (如果您的应用程序具有或使用其自己的事件循环,特别是如果它是Qt或GTK之上的GUI应用程序,则您希望对管道使用相同的事件循环;详细信息是提供该事件循环的库所特有的: g_spawn_async_with_pipes & g_source_add_unix_fd用于GTK, QProcess用于Qt ...)
I don't have time to explain how to do that (double piping into command + event loop) in details, but the Advanced Linux Programming book (available online) has several chapters on that. 我没有时间详细说明如何执行此操作(将双管道插入命令+事件循环),但是Advanced Linux Programming本书(可在线获得)中有几章。 Be aware that you need some event loop.
请注意,您需要一些事件循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.