Live graph for a C application - c

I have an application which logs periodically on to a host system it could be on a file or just a console. I would like to use this data to plot a statistical graph for me. I am not sure if I can use the live graph for my application.
If this tool is the right one, may I have an example on integrating the external application with the live graph?
this is livegraph link --> http://www.live-graph.org/download.html

I think this can be achieved easiest using Python plus matplotlib. To achieve this there are actually multiple ways: a) integrating the Python Interpreter directly in your C application, b) printing the data to stdout and piping this to a simple python script that does the actual plotting. In the following I will describe both approaches.
We have the following C application (e.g. plot.c). It uses the Python interpreter to interface with matplotlib's plotting functionality. The application is able to plot the data directly (when called like ./plot --plot-data) and to print the data to stdout (when called with any other argument set).
#include <Python.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
void initializePlotting() {
Py_Initialize();
// load matplotlib for plotting
PyRun_SimpleString(
"from matplotlib import pyplot as plt\n"
"plt.ion()\n"
"plt.show(block=False)\n"
);
}
void uninitializePlotting() {
PyRun_SimpleString("plt.ioff()\nplt.show()");
Py_Finalize();
}
void plotPoint2d(double x, double y) {
#define CMD_BUF_SIZE 256
static char command[CMD_BUF_SIZE];
snprintf(command, CMD_BUF_SIZE, "plt.plot([%f],[%f],'r.')", x, y);
PyRun_SimpleString(command);
PyRun_SimpleString("plt.gcf().canvas.flush_events()");
}
double myRandom() {
double sum = .0;
int count = 1e4;
int i;
for (i = 0; i < count; i++)
sum = sum + rand()/(double)RAND_MAX;
sum = sum/count;
return sum;
}
int main (int argc, const char** argv) {
bool plot = false;
if (argc == 2 && strcmp(argv[1], "--plot-data") == 0)
plot = true;
if (plot) initializePlotting();
// generate and plot the data
int i = 0;
for (i = 0; i < 100; i++) {
double x = myRandom(), y = myRandom();
if (plot) plotPoint2d(x,y);
else printf("%f %f\n", x, y);
}
if (plot) uninitializePlotting();
return 0;
}
You can build it like this:
$ gcc plot.c -I /usr/include/python2.7 -l python2.7 -o plot
And run it like:
$ ./plot --plot-data
Then it will run for some time plotting red dots onto an axis.
When you choose not to plot the data directly but to print it to the stdout you may do the plotting by an external program (e.g. a Python script named plot.py) that takes input from stdin, i.e. a pipe, and plots the data it gets.
To achieve this call the program like ./plot | python plot.py, with plot.py being similar to:
from matplotlib import pyplot as plt
plt.ion()
plt.show(block=False)
while True:
# read 2d data point from stdin
data = [float(x) for x in raw_input().split()]
assert len(data) == 2, "can only plot 2d data!"
x,y = data
# plot the data
plt.plot([x],[y],'r.')
plt.gcf().canvas.flush_events()
I have tested both approaches on my debian machine. It requires the packages python2.7 and python-matplotlib to be installed.
EDIT
I have just seen, that you wanted to plot a bar plot or such thing, this of course is also possible using matplotlib, e.g. a histogram:
from matplotlib import pyplot as plt
plt.ion()
plt.show(block=False)
values = list()
while True:
data = [float(x) for x in raw_input().split()]
values.append(data[0])
plt.clf()
plt.hist([values])
plt.gcf().canvas.flush_events()

Well, you only need to write your data in the given format of livegraph and set livegraph up to plot what you want. If wrote small C example which generates random numbers and dumps them together with the time every second. Next, you just attach the livegraph program to the file. That's it.
Playing around with LiveGraph I must say that its use is rather limited. I still would stick to a python script with matplotlib, since you have much more control over how and what is plotted.
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
int main(int argc, char** argv)
{
FILE *f;
gsl_rng *r = NULL;
const gsl_rng_type *T;
int seed = 31456;
double rndnum;
T = gsl_rng_ranlxs2;
r = gsl_rng_alloc(T);
gsl_rng_set(r, seed);
time_t t;
t = time(NULL);
f = fopen("test.lgdat", "a");
fprintf(f, "##;##\n");
fprintf(f,"#LiveGraph test file.\n");
fprintf(f,"Time;Dataset number\n");
for(;;){
rndnum = gsl_ran_gaussian(r, 1);
fprintf(f,"%f;%f\n", (double)t, rndnum);
sleep(1);
fflush(f);
t = time(NULL);
}
gsl_rng_free(r);
return 0;
}
compile with
gcc -Wall main.c `gsl-config --cflags --libs`

Related

Is it possible to dynamically load new functions to a running C program?

Consider the following C program:
#include <stdio.h>
const int OP_0 = 0;
const int OP_1 = 1;
const int OP_2 = 2;
int op_0(int x) {
return x + 2;
}
int op_1(int x) {
return x * 3 + 1;
}
int op_2(int x) {
return 2 * x * x - 10 * x + 5;
}
int compute(int op, int x) {
switch (op) {
case OP_0: return op_0(x);
case OP_1: return op_1(x);
case OP_2: return op_2(x);
}
return 0;
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
It is a very simple program that lets the user select one of 3 operations to perform on an int input. To use this program, we can compile it with, for instance, gcc program.c -o program, and then run it with ./program. That's all obvious. Suppose, though, that we wanted to add another operation:
int op_3(int x) {
return 900 + x;
}
If we wanted to use this new operation, we'd need to recompile the entire program. Adding a new operation to this program has O(n) complexity, and is slow since it requires a complete recompilation.
My question is: is it possible, in C, to let this program add new native operations (without writing an interpreter)? In other words, is it possible to dynamically compile and add op_3 to the C program above, without having to recompile everything?
For illustration purposes, here is an example of what I have in mind:
int compute(int op, int x) {
// the first time it runs, would load `op_N.dll`
// the next time, would use the loaded version
// so, to add a new operation, we just compile
// it and add `op_N.dll` to this directory
Fun op = dynamic_load(op);
return op(x);
}
The only way I can think of is to compile a new dynamic library that is then opened by the program using dlopen()...
Another way, similar but perhaps more primitive, would be to compile the code into an object file and then load it into a mmaped region with execution permissions, jumping then to it using a function pointer.
To do this, compile the new function using gcc -c, clean the binary code from the headers with objcopy -O binary -j .text. Now in the program open() the resulting file and use the mmap() function to map this file in memory, giving as protections PROT_READ | PROT_EXEC. You'd look up the manuals for all this functions.
Note that I am assuming that you are on a unix system. I don't know much about Windows, but I imagine that something similar could be done with VirtualAlloc().
Well, what you are asking is the "Open Principle of SOLID". To do so, you need to have a dynamic dlsym obviously after dlopen. To have a dynamic dlsym you need to be able to read header files or a file with the proper function prototypes. Yes, you need to cast function pointers, but the typecast depends upon the types of your parameter list.
Edit:
Hard coding dlsym means you have to relink your import library to your executable every time you add a function to your shared object.
OR
You have two shared objects. One is the import library, and the other is the library that you want to add functionality. As David Wheeler said, "All problems of computer science could be solved with another level of indirection, except for the problem with too many layers of indirection.".
Complete noob-proof answer. As the other answers suggested, we can use dlopen and dlsym to dynamically load a shared library on C. First of all, let's create the lib. Save the following file as 0.c
int fn(int x) {
return x * 10;
}
Then, run the following command to create the shared lib:
clang -shared 0.c -o 0
Now, we must edit our compute function to load fn from 0.c dynamically and use it. First, we declare an fn : int -> int function pointer:
int (*fn)(int);
Then, we convert the operation to decimal (since we saved the shared lib as 0, no extension):
char file[256];
sprintf(file, "%d", 0);
Then, we load 0 dynamically:
void *handle = dlopen(file, RTLD_LAZY);
Then, we find fn on that lib, and assing to the fn function pointer:
*(void**)(&fn) = dlsym(LIB[op], "fn");
Then, we can just call it!
fn(5) // will return 50
Here is a complete example, that handles errors and stores the function pointers in a jump table (so we don't need to re-load the lib every time, obviously!):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
const int MAX_OPS = 256;
// Jump-table with available functions
int (*OP[MAX_OPS])(int);
// Array with shared libraries
void* LIB[MAX_OPS];
// Loads an operation dynamically
void load_op(int op) {
int (*fn)(int);
// Generates the file name
char file[256];
sprintf(file, "%d", op);
// Opens the dynamic lib
LIB[op] = dlopen(file, RTLD_LAZY);
// Handles error opening the lib
if (!LIB[op]) {
fprintf(stderr, "Couldn't load operation: %s\n", dlerror());
}
// Creates the function pointer
*(void**)(&fn) = dlsym(LIB[op], "fn");
// Handles error finding the function pointer
if (!fn) {
fprintf(stderr, "Couldn't load operation: %s\n", dlerror());
dlclose(LIB[op]);
}
// Adds to jump table
OP[op] = fn;
}
// Clears the dynlib objects
void close_ops() {
for (int op = 0; op < MAX_OPS; ++op) {
dlclose(LIB[op]);
}
}
// Applies the specified operation to an input
// Requires a shared object file with a name equivalent to the decimal
// representation of op to be loaded on the current directory
int compute(int op, int x) {
if (!OP[op]) {
load_op(op);
}
return OP[op](x);
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
All the credit to the people who took their time to answer my question here and on #c on Libera.Chat. Thank you!

How to call C function from nodeJS

I have some C functions that I need to call frequently from nodeJS (less than 1 second time intervals). The C function takes in an argument and returns a value, which might be an int or an array.
It can be as simple as below:
int main() {
int x = 2;
return x;
}
And I need to get the value x in nodeJS and be able to do console.log(x)
I tried using node-ffi, but I read from the internet that it has a large overhead and is thus inefficient for frequent function calls.
I also considered writing addons but it seems very troublesome (with unfamiliar V8, C++ code and all that...)
And there is not much resources regarding integration between nodeJS and C (they are mostly nodeJS with C++)
Could somebody help shed some light on this? Thanks.
change your c code to
// myProgram.c
#include <stdio.h>
int main(void){
puts("4");
return 0;
}
compile it with gcc, in the same directory as your node file
$ gcc -o myProgram myProgram.c
in your node file, require exec()
const { exec } = require("child_process");
and use it like so:
exec("./myProgram", (error, stdout, stderr) => console.log(stdout));
This works well, it spins up a new process every time.
If, on the other hand, you want to keep the child process running, and call a function in that code from node, you can do that like this:
// multiplyBy2.c
#include <stdio.h>
#include <stdlib.h>
int timesTwo(int x){
return x*2;
}
int main(void){
char buff[100];
int input,output;
while(1){
gets(buff);
input = atoi(buff);
output = timesTwo(input);
printf("%d", output);
// you must flush stdout or else node will hang!
fflush(stdout);
}
return 0;
}
compile multiplyBy2.c and then:
// myNodeApp.js
const {spawn} = require('child_process');
const __delay__ = t => new Promise(resolve=>setTimeout(()=>resolve(), t))
const ch = spawn('./multiplyBy2')
var result=undefined;
ch.stdout.on("data",(data)=>{
result = parseInt(data.toString())
})
async function multiplyBy2InC(num){
ch.stdin.write(`${num}\n`)
while(result==undefined)
await __delay__(1)
const output = result
result = undefined
return output
}
// now you could call it like this, it will print 20 to the console
multiplyBy2InC(10).then(r=>console.log(r))
Use a child process.
,.........
https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback

Accessing custom XResources colors with X11

I'm just starting my first ever program using the X11 library. To start, I'm just trying to access the colors from the user's color-scheme as defined in xrdb. For example, in my ~/.Xresources I have things like:
*color8: #073642
*color0: #002b36
I've also verified that these colors show up when I run xrdb -query. In my C program so far I have:
#include <X11/Xlib.h>
#include <X11/Xresource.h>
int main (int argc, char *argv[])
{
Display* display = XOpenDisplay (0);
XrmDatabase xrdb = XrmGetDatabase (display);
XrmValue v;
Colormap cmap = DefaultColormap (display, DefaultScreen (display));
XColor screenColor;
XColor exactColor;
if (! XAllocNamedColor (display, cmap "color0", &screenColor, &exactColor))
printf ("ERROR\n");
printf ("%u %u %u\n", screenColor.red, screenColor.green, screenColor.blue);
return 0;
}
But this errors. So what am I missing? Is there a better way to do what I'm trying to do? Thanks!
When you want to access parameters set in an Xresource file loaded by xrdb, you need to
xrdb = XrmGetStringDatabase(XResourceManagerString(display));
instead of XrmGetDatabase(...). Hope that addresses (lately) your question.

Running a terminal command from a C program in OS X

I'm trying to use plotutils to generate a plot from binary data. First, I wrote a C program to export some sample binary data. Then, when I execute the following command in terminal, the plot gets generated as expected.
graph -T png -I d <'/Users/username/Documents/Restofpath/PlotutilsDataGen/testData'> '/Users/username/Documents/Restofpath/PlotutilsDataGen/testPlot.png'
But I want to combine this command with the C code that generates the binary data file so that once the code is executed, the plot is automatically exported. I tried two approaches: (i) using popen() which I suspect I'm doing incorrectly, and (ii) using system() which I thought should work, but doesn't. My entire code is as follows (I've listed both approaches together in the code by I naturally tried them individually):
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int numSamples = 1024;
double outputVec[2*numSamples];
char outputPath[200] = "/Users/username/Documents/Restofpath/PlotutilsDataGen/testData";
char plotcommand[400] = "graph -T png -I d <'/Users/username/Documents/Restofpath/PlotutilsDataGen/testData'> '/Users/username/Documents/Restofpath/PlotutilsDataGen/testPlot.png'";
FILE *fp, *p;
// Compute sample functions to export
for(int ii = 0; ii < (2*numSamples); ii = ii + 2)
{
outputVec[ii] = (double)ii/2;
outputVec[ii+1] = (double)(ii*2);
}
// Export as binary data file for plotutils to use for plotting
fp = fopen(outputPath, "wb");
fwrite(outputVec, sizeof(double), 2*numSamples, fp);
fclose(fp);
// Option 1
p = popen(plotcommand, "w");
pclose(p);
// Option 2
system(plotcommand);
return 0;
}
Any ideas as to what I'm doing wrong or how I might get this to work? Thanks.

Why am I getting a "Segmentation Fault" error when I try to run the tests?

I've written a function that determines whether or not to assign default values (it assigns default values if the flag is not present, and it assigns values the user passes if the flag is present). And I'm trying to test my function with a string to see if it did give me the right numbers. I keep getting "Segmentation Fault" when I try to run the tests, it compiles, but the tests just don't work. :(
Here's my header file:
#ifndef COMMANDLINE_H
#define COMMANDLINE_H
#include "data.h"
#include <stdio.h>
struct point eye;
/* The variable listed above is a global variable */
void eye_flag(int arg_list, char *array[]);
#endif
Here's my implementation file:
#include <stdio.h>
#include "commandline.h"
#include "data.h"
#include "string.h"
/* Used global variables for struct point eye */
void eye_flag(int arg_list, char *array[])
{
eye.x = 0.0;
eye.y = 0.0;
eye.z = -14.0;
/* The values listed above for struct point eye are the default values. */
for (int i = 0; i <= arg_list; i++)
{
if (strcmp(array[i], "-eye") == 0)
{
sscanf(array[i+1], "%lf", &eye.x);
sscanf(array[i+2], "%lf", &eye.y);
sscanf(array[i+3], "%lf", &eye.z);
}
}
}
And here are my test cases:
#include "commandline.h"
#include "checkit.h"
#include <stdio.h>
void eye_tests(void)
{
char *arg_eye[6] = {"a.out", "sphere.in.txt", "-eye", "2.4", "3.5", "6.7"};
eye_flag(6, arg_eye);
checkit_double(eye.x, 2.4);
checkit_double(eye.y, 3.5);
checkit_double(eye.z, 6.7);
char *arg_eye2[2] = {"a.out", "sphere.in.txt"};
eye_flag(2, arg_eye2);
checkit_double(eye.x, 0.0);
checkit_double(eye.y, 0.0);
checkit_double(eye.z, -14.0);
}
int main()
{
eye_tests();
return 0;
}
The absolute easiest way to solve this one is run it in a debugger. You probably won't even need to learn how to step through your code or anything - just fire up, run, and read the line.
If you are on a *nix system:
Compile your code with -g flag.
Load as, e.g. gdb a.out.
Run now that it's loaded - (gdb) run.
Do whatever you need to reproduce the segfault.
bt or where should give you a stack trace - and an exact line that is causing your problem.
I'm sure enough you can solve it from there to post this as an answer; but if not, knowing the exact line will make it very much easier to research and solve.
The errors are here:
for (int i = 0; i <= arg_list; i++)
{ ///^^
if (strcmp(array[i], "-eye") == 0)
{
sscanf(array[i+1], "%lf", &eye.x);
//^^^
sscanf(array[i+2], "%lf", &eye.y);
sscanf(array[i+3], "%lf", &eye.z);
}
}
i <= arg_list is wrong since you pass in 6, array index starts from 0, the max value is 5
i+1, i+2,i+3 will give you out of bounds index when you iterate from 0 to 5.
Your loop condition is wrong. It should be i < arg_list.
Think about what happens when i == arg_list.

Resources