Template:ROOT/Exercises/A Simple Stand-Alone Application
Exercise
[edit source]Once again, consider the code you should have previously written to compute the mean of an array of random numbers. Now, last but not least, make it a stand-alone application and run it independently of any ROOT session. Make sure that passing parameters will still work. Check the performance of your application. Take also care that your modifications don't disturb interpretation or on-the-fly compilation by CINT or ACLiC.
Solution
[edit source]What we have to do is to add an int main()
function. But this will bother CINT. So we hide it by putting a preprocessor command around it that will ignore it if the variable __CINT__
is defined.
# ifndef __CINT__ // the following code will be invisible for the interpreter
int main()
{
random_mean();
}
# endif
This works. But it doesn't allow us to pass command line arguments yet. So to make it complete, we add a check if any parameters are given and if so, we convert the second (the first is—as always—the name of the application) to an integer and call random_mean
with it. The conversation may be done with the strtof
method that can be found in the cstdlib
.
The final code should look like this:
// compile with: g++ -o random_mean random_mean.cc `root-config --cflags --glibs`
# include <cstdlib> // needed to convert string argument to integer
# include <iostream>
# include "TRandom.h"
using namespace std;
void random_mean(Int_t nums)
{
TRandom *R = new TRandom(time(0));
Double_t *seed = new Double_t[nums];
for (Int_t i = 0; i < nums; i++)
{
seed[i] = R->Rndm();
}
Double_t mean = 0.0;
for (Int_t i = 0; i < nums; i++)
{
mean += seed[i];
}
mean /= nums;
cout << "mean = " << mean << endl;
}
void random_mean()
{
random_mean(100000000); // on default, take 1E8 numbers
}
# ifndef __CINT__ // the following code will be invisible for the interpreter
int main(int argc, char **argv)
{
if (argc == 1) // no parameter given
{
random_mean();
}
else
{
Int_t parameter = (Int_t) strtof(argv[1], NULL); // convert the second parameter to an integer
random_mean(parameter);
}
}
# endif
Now we can compile the code using an external compiler
g++ -o random_mean random_mean.cc `root-config --cflags --glibs`
and also execute it without starting ROOT. With or without a parameter. Check out how fast it is!
./random_mean 34
mean = 0.500596
./random_mean
mean = 0.500062
Note that is is still possible to interpret or compile your macro on-the-fly.
root [0] .x random_mean.cc(10) |
mean = 0.568087 |
root [1] .x random_mean.cc+(10) |
Info in <ACLiC>: script has already been loaded in interpreted mode Info in <ACLiC>: unloading /home/tux/Desktop/test/./random_mean.cc and compiling it mean = 0.535071 |
So after a long journey, we have finally made the ultimate ROOT source file. I also recommend this strategy when developing something new. First try it interactively. If you know what to do, start writing your macro and test it on the interpreter. If it is more or less finished, make sure the code is clean and test it on larger amounts of data as compiled code. And finally make it a stand.alone application (if needed). It is wonderful that ROOT supports all these possibilities.
One more thing to note: This was a basic example. To build a stand-alone application with a ROOT GUI a slightly more difficult setup is needed.