Running a terminal command from a C program in OS X - c

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.

Related

Opening files in C in Xcode

#include <stdio.h>
#include <math.h>
int main(void) {
int i=0;
int number =0;
float vector[100];
float sum=0., mean = 9., stdev=0.;
FILE *fp_in = NULL;
fp_in = fopen("stat_data.txt","r");
if(fp_in != NULL)
{
fscanf(fp_in,"%d",&number);
for (i=0; i < number; i++)
{
fscanf(fp_in, "%f", &vector[i]);
sum += vector[i];
}
mean = sum/number;
printf("Mean = %f\n",mean);
sum=0.0;
for(i=0; i<number;i++)
{
sum+= pow(vector[i]-mean,2);
}
stdev = sqrt(sum/(number - 1));
printf("standard deviation is %f\n", stdev);
}
else
{
printf("Opening of file stat_data.txt failed\n");
}
return 0;
}
I'm trying to open the text file "stat_data" in Xcode and it works on a linux computer, but it doesn't seem to work on Xcode. I think there's something wrong with the settings but I don't know what it could be.
Screenshot of the IDE showing where the stat_data.txt is placed -
This happened because the place where the Xcode created de binary file is different where your txt file is locate.
So I put my txt file in the same directory of my binary (readFile).
In the picture I list where my source and binary file are locate.
If you don't know where your binary file is. You can show it f you don't know where your binary file is. You can show it using the "show in finder".
So my result is it:
File opened.
Because you do not specify a path to the file name when you open it, the program expects the file to be in the current working directory which is set by Xcode when you run the program in Xcode and set by the shell when you run the program from the command line (as the directoy you are in when you run it).
There are two ways to get around this:
specify an absolute path when you open the file e.g.
/Users/thiagmarques/path/to/stat_data.txt
Edit the scheme to run from the directory containing the file. If you click on "Edit Scheme" and then select the Run section. The Options tab has a check box to "Use custom working directory". Check this and enter the directory containing your text file.

Creating array of strings works in source code doesn't work in executable

I've got some code which generates an array of strings of different file names and then
passes them into a function to write some data to them. It adds a incrementing number to the starting filename which is supplied from an input argument.
The problem is that it works fine running from source in Visual Studio 2012 but when I compile it and run it as an .exe the program crashes.
The .exe doesn't appear to be passing the array of strings properly which is causing an error when it attempts to use the string
for opening a file etc.
Here is the isolated bit of code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <Windows.h>
void processing_function(int num_output, char **outnames)
{
/* in Visual Studio this works fine and prints all
the names correctly. Running from .exe will crash */
for(int idx = 0; idx <num_output;idx++)
{
printf("outnames[%d] is %s\n",idx,outnames[idx]);
}
}
int main(int argc, char *argv[])
{
/*nframes comes from another function, outname comes from input arguement */
int num_output = ceil(((double)*nframes / 1100));
int outname_len = strlen(outname)+1;
char *out_right;
out_right = (char*) malloc(sizeof(char)*outname_len);
/*Split string to append numbers before file extension */
strcpy(out_right,outname);
strrev(out_right);
strtok(out_right,".");
strcat(out_right,".");
strrev(out_right);
int out_right_len = strlen(out_right);
strtok(outname,".");
strcat(outname,"-");
int out_origlen = strlen(outname);
int num_len = 1;
char **outnames;
char *num;
char *outname_tmp;
outnames = (char**) malloc(sizeof(char)*(num_output));
int out_len;
double dbl_idx;
int *numfs = (int*)malloc(sizeof(int)*num_output);
for(int idx = 1;idx <num_output+1;idx++)
{
/*convert output number to string and stitch complete name back together and place into array */
num_len = ceil(log10((double)idx+0.1));
num = (char*) malloc(sizeof(char)*(num_len+1));
outname_tmp = (char*) malloc(sizeof(char)*(out_origlen+num_len+out_right_len+1));
strcpy(outname_tmp,outname);
sprintf(num,"%d",idx);
strcat(outname_tmp,num);
free(num);
strcat(outname_tmp,out_right);
outnames[idx-1] = (char*) malloc(sizeof(char)*(out_origlen+num_len+out_right_len+1));
strcpy(outnames[idx-1],outname_tmp);
free(outname_tmp);
printf("%s\n",outnames[idx-1]);
}
free(out_right);
processing_function(num_ouput, outnames)
return(0);
}
EDIT: Changed num_input to num_output as they do have the same value.
Running from .exe will sometimes start printing some of the names and then crash, opening the
debugger gives an error within output.c, with an access reading violation. I tried putting this code at
the top of the processing_function but that gave further problems downstream (heap corruption), which makes me think that the
code is messing up the memory but I can't see whats wrong with it, nor why it would work in VS but not as a .exe.
I could try and dodge the issue by generating the next output name on the fly every time it requires one but I'd really rather know why this isn't working.
Any help would be greatly appreciated.
I am going to take a shot and say, you passed num_input to processing_function() with outnames, outnames was allocated with num_output for size, but num_input and num_output have different values at runtime. So that lets processing_function() access out of bounds.

Matlab-generated Dll in C

I created a dll of a simple function in Matlab using this command:
mcc -t -L C -W lib:testfunctionLib -T link:lib testfunction.m libmmfile.mlib
The simple function looks like:
function y = testfunction(x)
y = x + 10;
end
I need to call the dll via c-code. This is what i'm using to get the result of the computation with the dll-function into a textfile:
#include <windows.h>
#include <stdio.h>
int main()
{
int z = 1;
FILE *Testfile;
typedef int(*BinaryFunction_t) (int);
BinaryFunction_t AddNumbers;
int result;
BOOL fFreeResult;
HINSTANCE hinstLib = LoadLibraryA("testfunctionLib.dll");
if (hinstLib != NULL)
{
AddNumbers = (BinaryFunction_t)GetProcAddress(hinstLib, "testfunction");
if (AddNumbers != NULL)
result = (*AddNumbers) (z);
fFreeResult = FreeLibrary(hinstLib);
Testfile = fopen("Testfile.txt", "a");
fprintf(Testfile, "%i\n", result);
fclose(Testfile);
}
else
{
Testfile = fopen("Testfile.txt", "a");
fprintf(Testfile, "NOT");
fclose(Testfile);
}
}
I always get a 'NOT' in my textfile because the c-code can't extract the function out of the dll. Why doesn't this work? The c-code for getting the dll-function should be ok, i tested it with a dll created within visual studio.
I know that the library failed to load, but i don't receive any error message.. I also tried to build the dll by the Matlab Coder. I get i lot of different files (c,h,etc) and a single dll-file called testfunction. But including this dll is still not working..

Importing C functions in System Verilog with file-type Argument

I am trying to import a C function into a System verilog test bench. The code for the C function is as shown below. I want to pass files as arguments. The function basically reads from one file and writes to another.
int readmem(int z, FILE *file1, FILE *file2) {
char data;
int x;
int i;
for(i = 0; i<z;i ++) {
data = fgetc(file1);
x = data;
fputc(x,file2);
}
return 0;
}
Kindly advise me on how I could call this function in a System verilog test bench.
You cannot pass file descriptors between SystemVerilog and C via the DPI, so I don't think it's possible to import the function directly as-is.
If all you really need to do is get the functionality in SystemVerilog, it will be easier to just port it to SystemVerilog rather than trying to import it via the DPI.
Something like this should work (not tested!):
function int readmem(int z, int file1, int file2);
reg[8:0] data;
for (int i = 0; i < z; i++) begin
data = $fgetc(file1); // Really should break out of the loop if data == EOF ('h1FF)
$fwrite(file2, "%c", data[7:0]);
end
return 0;
endfunction
Then from somewhere else:
int file1 = $fopen("input_file", "r");
int file2 = $fopen("output_file", "w");
readmem(10, file1, file2)
The reason data is declared as 9 bits is to capture an EOF if the end of file is reached. Your original function could run past the end of file1 since you are not checking for EOF.
SystemVerilog includes DPI (Direct Programming Interface) which lets your SystemVerilog call C functions and can even let your C call SystemVerilog tasks/functions. Check out IEEE std 1800-2009 Section 35 and Annex H & I. There are limitations with data types so check out Annex H.7.4 that for basic SV/C type mapping.
To call C functions in SystemVerilog, simply import it into the desired scope (e.g. module or package)
import "DPI-C" context function C_function_name(/* args */);
To call SystemVerilog from C requires one extra step.
In SV :
export "DPI-C" function SV_function_name; /*no args */
In C :
extern return_type SV_function_name( /* args */);
Depending on your simulator you may need to compile the C code first and reference the object file, or just include the source file in your file list. You make need to add options to your simulator to, so check the manual.
Here are some resources that can help you get started:
http://en.wikipedia.org/wiki/SystemVerilog_DPI
http://www.doulos.com/knowhow/sysverilog/tutorial/dpi/
http://www.asic-world.com/examples/systemverilog/dpi.html
Revision:
Use a translate wrapper since FILE does does not translate across DPI. C's const char* maps to SystemVerilog's string.
C:
#include <stdlib.h>
#include <stdio.h>
// include for DPI
#include "svdpi.h"
// wrapper
int C2SV_readmem(int z, const char *filename1, const char *filename2) {
FILE *file1;
FILE *file2;
int rtn;
file1 = fopen(filename1, "r");
file2 = fopen(filename2, "w");
if (file1 == NULL) {
printf("failed to open '%s' for read\n", filename1);
return 1;
}
if (file2 == NULL) {
printf("failed to open '%s' for write\n", filename2);
return 1;
}
return readmem(z, file1, file2); // call original readmem function
}
/* ... */
SystemVerilog:
module test;
import "DPI-C" context function int C2SV_readmem(input int z, input string filename1, input string filename2);
int value;
initial begin
value = C2SV_readmem( 25, "FileIn.txt", "FileOut.txt");
end
endmodule

Live graph for a C application

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`

Resources