我想在仿真过程中做一些实时绘图。为此,我想使用八度或gnuplot。我当前的方法是使用前端来gnuplot,feedgnuplot,这实际上非常合适。

模拟是用C ++编写的,因此我考虑了分叉(feedgnuplot的新过程)并将相关数据传递给feedgnuplot。

我的问题是输出仅在仿真后可见。
但是我想看看模拟过程中的情节更新。

这是MWE:

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>

int main()
{
    FILE* stream = popen("feedgnuplot", "w");

    for(int i = 0; i < 10; ++i)
    {
        fprintf(stream, "%d\n", i * i);
        fflush(stream);
        sleep(1);
    }
}


程序在10秒后停止,显示图。

直接在外壳中使用feedgnuplot时,一切都会按预期进行。
(也就是说,无需结束过程即可绘制新添加的数据)

我究竟做错了什么?我认为我对Popen的实际运作方式缺乏了解。

最佳答案

首先,让我们编写一个假的feedgnuplot.c:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *buf = NULL;
    size_t n = 0;

    while (getline (&buf, &n, stdin) != -1) {
        printf ("%s", buf);
    }

    free (buf);
    return 0;
}


这样,您的代码就可以工作,即行到达时即进行打印。

我怀疑问题出在您的feedgnuplot程序读取传入数据的方式上。您应该显示该代码的相关部分。

如果我不得不猜测,您可能需要添加

setvbuf (stdin, NULL, _IOLBF, 0);


在开始从stdin读取之前,在feedgnuplot中。

这是因为默认情况下,当stdin对应于终端时,它被行缓冲,而当它对应于管道时,它被完全缓冲。上面的代码无论如何都将stdin行缓冲,因此从终端或管道读取之间应该没有区别。

10-05 18:04