Since it is ideal for carrying out analyses in signal processing and you often want/need to display the signals graphically, I use Gnuplot as a C call. For me, this has the advantage of being able to share commands with colleagues without any complications and also shows the perfect integration of Zig and C.
Maybe some of you also need it, which is why I am sharing my Zig code here:
fn plot_data(data: []Complex(f32)) !void {
const c = @cImport({
@cInclude("stdio.h");
});
const gnuplot = c.popen("gnuplot -persistent", "w");
defer _ = c.pclose(gnuplot);
_ = c.fprintf(gnuplot, "set title 'Sequence - L: %d'\n", data.len);
_ = c.fprintf(gnuplot, "set xlabel 'Index'\n");
_ = c.fprintf(gnuplot, "set ylabel 'Value'\n");
_ = c.fprintf(gnuplot, "set grid\n");
_ = c.fprintf(gnuplot, "plot '-' with lines linecolor 6 notitle");
// Send data
for (data, 0..) |v, i| {
_ = c.fprintf(gnuplot, "%d %f\n", i, v.re);
}
// End of data
_ = c.fprintf(gnuplot, "e\n");
}
We are in a project and it should be quick, so I didnāt try to implement it with āstd.process.Childā. So no. If there is a simple solution for this, please let me know.
Unfortunately wait is necessary to release resources.
A deinit must be provided from Child to release resources without waiting or killing the process.
But you will leak userspace process and io streams handles/descriptors, thatās why wait() or kill() is crucial. Few bytes leaked is not a big deal though
I wish for API to āreleaseā child process without needing to wait or kill it.
==32479== Memcheck, a memory error detector
==32479== Copyright (C) 2002-2024, and GNU GPL\'d, by Julian Seward et al.
==32479== Using Valgrind-3.23.1.GIT and LibVEX; rerun with -h for copyright info
==32479== Command: ./plot_signal fft_tap.bin
==32479==
==32479==
==32479== HEAP SUMMARY:
==32479== in use at exit: 0 bytes in 0 blocks
==32479== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==32479==
==32479== All heap blocks were freed -- no leaks are possible
==32479==
==32479== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
I am using a buffer allocator, so every memory will be freed after finishing the program. Or do I oversee something?
Thereās no memory leak but handle/descriptor leak so you see nothing in valgrind. I have to say that this doesnāt matter if your program is a āsingle-shotā. Problems will only arise if you do spawn thing many times.