I installed root with fixed location on a x86_64 architecture. I am trying to replicate the tutorial graphs/graph.C but I experience some errors.
First of all, if I include root headers in the usual way
I get this error
RandomWalk.cpp:8:20: fatal error: TCanvas.h: No such file or directory
When I put the full path for .h files
I get undefined reference errors
/tmp/ccaKR0dl.o: In function `main':
RandomWalk.cpp:(.text+0x578): undefined reference to `TCanvas::TCanvas(char const*, char const*, int, int, int, int)'
RandomWalk.cpp:(.text+0x6a0): undefined reference to `TGraph::TGraph(int, double const*, double const*)'
RandomWalk.cpp:(.text+0x83c): undefined reference to `TObject::operator delete(void*)'
RandomWalk.cpp:(.text+0x84c): undefined reference to `TObject::operator delete(void*)'
/tmp/ccaKR0dl.o: In function `__static_initialization_and_destruction_0(int, int)':
RandomWalk.cpp:(.text+0x924): undefined reference to `TVersionCheck::TVersionCheck(int)'
/tmp/ccaKR0dl.o: In function `TObject::operator new(unsigned long)':
RandomWalk.cpp:(.text._ZN7TObjectnwEm[TObject::operator new(unsigned long)]+0x14): undefined reference to `TStorage::ObjectAlloc(unsigned long)'
/tmp/ccaKR0dl.o: In function `TCanvasImp::IsA() const':
RandomWalk.cpp:(.text._ZNK10TCanvasImp3IsAEv[TCanvasImp::IsA() const]+0xd): undefined reference to `TCanvasImp::Class()'
/tmp/ccaKR0dl.o:(.rodata._ZTV10TCanvasImp[vtable for TCanvasImp]+0xf8): undefined reference to `TCanvasImp::ShowMembers(TMemberInspector&)'
/tmp/ccaKR0dl.o:(.rodata._ZTV10TCanvasImp[vtable for TCanvasImp]+0x100): undefined reference to `TCanvasImp::Streamer(TBuffer&)'
collect2: ld returned 1 exit status
Can anyone help me? I attach the relevant cpp code.
RandomWalk.cpp (2.13 KB)
Try the following which works for me.
g++ -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/root -g -O2 -c RandomWalk.cpp
This will generater RandomWalk.o
libtool --mode=link g++ -g -O2 -o RandomWalk RandomWalk.o -L/usr/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lz -lGui -pthread -lm -ldl -rdynamic /usr/lib/libf2c.a
This will generater RandomWalk executable file. ( Notice it’s only one line)
Also you don’t need all -l* options, just play with it.
You may have to change the -I/usr/include/root and -L/usr/lib/root
First of all thanks for the reply.
This works fine, I got the .o
For the second part I needed to install f2c. After that the only file available was libf2c.so and I tried it without success
libtool --mode=link g++ -g -O2 -o RandomWalk RandomWalk.o -L/usr/lib64/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lz -lGui -pthread -lm -ldl -rdynamic /usr/lib64/libf2c.so
I got this error
libtool: link: g++ -g -O2 -o RandomWalk RandomWalk.o -pthread -rdynamic /usr/lib64/libf2c.so -L/usr/lib64/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lz -lGui -lm -ldl -pthread
/usr/lib64/libf2c.so: undefined reference to `MAIN__'
collect2: ld returned 1 exit status
Deleting /usr/lib/libf2c.so from the command line works but then at runtime I got NO canvas: the program runs and ends without displaying the graph.
Did you create a TApplication object in your main?
You don’t need the f2c for your code. Sorry I post it because I use it.
So you can remove the last term when you compile from o to exe file
The graph is what I added in your code just to show you it worked.
Just add one line after c1->Update
TGraph* gr = new TGraph(n,ord,absc);
I finally succedeed! Thanks a lot gjzeus for your help. I attach the final .cpp. Let me summarize for clarity:
Obtained the .o with
g++ -Wall -I/home/Guido/root/include -c RandomWalkROOT.cpp
Obtained the executable with
g++ -O2 -m64 RandomWalkROOT.o -L/home/Guido/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic -o RandomWalkROOT
The code runs, at the end I get the file “Rw.png”. Just another question:
I still have no window for the graph displayed at runtime. In my opinion, I get it with the method TGraph::Draw() but this seems doing nothing.
@Philippe: I have never heard about TApplication class, and never used. Why would I create such an object?
RandomWalkROOT.cpp (3 KB)
The TApplication object (see root.cern.ch/root/html/TApplication.html) is the ‘GUI application singleton’ that properly enabled the graphical display.
I included TApplication in my code and I get the canvas on the screen. Still sounds strage to me because I didn’t ever need a TApplication object to obtain canvas at runtime (as far as I remember)
Here is how I modified the code
TApplication* theApp = new TApplication(“App”, 0, 0);
TCanvas* c1 = new TCanvas(“c1”,“Graph”,0,0,700,500);
c1->Connect(“Closed()”, “TApplication”, theApp, “Terminate()”);
Int_t n = NSTEP.size();
Double_t ord[n], absc[n];
TGraph* gr = new TGraph(n,absc,ord);
cout << “Running” << endl;
cout << “Terminating” << endl;
cout << “Done” << endl;
However I can’t really go back to the main, because as soon as I close the canvas the program ends. Using Terminate() doesn’t help, the program never outputs the string “Terminating”.
After the call to Run(), you should be able to go the canvas menu and select File/Quit ROOT. If this interface is not convenient in your application, we first would need to decide on the behavior that is needed (should the canvas be shown for a given amount of seconds or for a user determined amount, etc.?)
Actually I can go to canvas menu and click Quit ROOT, but then the entire program ends and, in any case, this is not convenient for me. What should I use to show the canvas for a give/user determined amount of time?
Sorry for this question, seems that I didn’t do the homework but actually I couldn’t find anything on this.
Instead of calling Run(), implement a loop (terminated any way you want) that call gSystem->ProcessEvents().
I did it but something is wrong. TSystem is and abstract class and I get this error
I added just two lines
TSystem* gSystem = new TSystem();
Should I inherit an entire class from TSystem in order to be able to call ProcessEvents()? I don’t understand how I should do it properly
You should not create the gSystem pointer nor allocate a TSystem object. There is already one created for you (with the correct implementation for the platform you use). After include TSystem.h you ought to be able to use gSystem directly.