I'm a little confused about how the "link" pragmas work and what they
are doing. The motivation for my asking is that I would like to be
able to pass the existing source through rootcint and have it generate
interface stubs for the extern's and classes they contain, so that the
variables are visible to the parser, without having to write a
seperate "pragma link" statement for each class, variable,...
Below are five small files of a simple little test code: Main.C,
TestClass.h, TestClass.C, and LinkDef.h. The LinkDef.h file uses the statement
#pragma link off all globals
etc, which should turn off generation of interface stubs, and it then
then lists each variable, class, etc for which an interface should be created:
#pragma link C++ global gX
This works. My understanding, however, from looking at the file
UTILS_rootcint.cxx and also the documentation on makecint, is that by
default an interface stub will be created for all global symbols and
defined classes, which would be equivalent to
#pragma link C++ all classes
etc. However, when I do this, I get
> rootcint -f MyDict.C -c TestClass.h LinkDef.h
> Note: operator new() masked 1c
> Note: operator delete() masked 1c
> class TMemberInspector in /usr/home/rge/Root/root.v1.03/include/TMemberInspector.h line 26 original base of virtual func
> class TObject in /usr/home/rge/Root/root.v1.03/include/TObject.h line 67 original base of virtual func
> class TIterator in /usr/home/rge/Root/root.v1.03/include/TIterator.h line 25 original base of virtual func
> class TIter in /usr/home/rge/Root/root.v1.03/include/TCollection.h line 108 original base of virtual func
> class TString in /usr/home/rge/Root/root.v1.03/include/TString.h line 148 original base of virtual func
> class TObjLink in /usr/home/rge/Root/root.v1.03/include/TList.h line 86 original base of virtual func
> class TDatime in /usr/home/rge/Root/root.v1.03/include/TDatime.h line 22 original base of virtual func
> class TestClass1 in TestClass.h line 11 original base of virtual func
> Warning: Link requested for undefined class TClass FILE: LINE:0
> Warning: Link requested for undefined class ofstream FILE: LINE:0
> Warning: Link requested for undefined class TBrowser FILE: LINE:0
> Warning: Link requested for undefined class TObjArray FILE: LINE:0
> Warning: Link requested for undefined class TMethod FILE: LINE:0
> Warning: Link requested for undefined class TMap FILE: LINE:0
.
.
.
And it doesn't compile:
> g++ -g -Wall -fPIC -I/usr/home/rge/Root/root.v1.03/include -c MyDict.C -o MyDict.o
> MyDict.C: In function `int G___va_start_1_0(struct G__value *, char *, struct G__par
> am *, int)':
> MyDict.C:6008: non-lvalue in assignment
> MyDict.C: In function `void G__cpp_setup_globalMyDict(...)':
> MyDict.C:8634: non-lvalue in unary `&'
> MyDict.C:8635: non-lvalue in unary `&'
> MyDict.C:8636: non-lvalue in unary `&'
The last three errors refer to these three lines in MyDict.C:
G__memvar_setup((void*)(&stdout),69,0,0,-1,-1,-1,1,"stdout=",0,(char*)NULL);
G__memvar_setup((void*)(&stderr),69,0,0,-1,-1,-1,1,"stderr=",0,(char*)NULL);
G__memvar_setup((void*)(&stdin),69,0,0,-1,-1,-1,1,"stdin=",0,(char*)NULL);
I've tried turning off default generation of stubs for classes and
leaving it on for functions and globals, and turning if off for both
functions and classes, and if I leave off the LinkDef.h file
completely, I get
> rootcint -f MyDict.C -c TestClass.h
> Note: operator new() masked 1c
> Note: operator delete() masked 1c
> Warning: Link requested for undefined class TestClass FILE: LINE:0
> g++ -g -Wall -fPIC -I/usr/home/rge/Root/root.v1.03/include -c MyDict.C -o MyDict.o
> Linking myroot ...
> g++ -g Main.o TestClass.o MyDict.o -L/usr/X11/lib -L/usr/home/rge/Root/root.v1.03/li
> b -lNew -lBase -lCint -lClib -lCont -lFunc -lGraf -lGraf3d -lHist -lHtml -lMatrix -l
> Meta -lMinuit -lNet -lPostscript -lProof -lRint -lTree -lUnix -lZip -lGpad -lGX11 -l
> Motif -lWidgets -lX3d -ldl -lXm -lXt -lX11 -lm -rdynamic -o myroot
> TestClass.o: In function `TestClass1::Dictionary(void)':
> /usr/home/rge/Root/root.v1.03/MyTests4/TestClass.C:12: undefined reference to `TestClass1::DeclFileLine(void)'
> /usr/home/rge/Root/root.v1.03/MyTests4/TestClass.C:12: undefined reference to `TestClass1::DeclFileName(void)'
> /usr/home/rge/Root/root.v1.03/MyTests4/TestClass.C:12: undefined reference to `TestClass1::Class_Version(void)'
> TestClass.o: In function `__TestClass1Init__::__TestClass1Init__(void)':
> /usr/home/rge/Root/root.v1.03/MyTests4/TestClass.C:12: undefined reference to `TestClass1::Class_Version(void)'
> make: *** [myroot] Error 1
This, strangely, is a different behavior from when LinkDef.h says
#pragma link all classes
which I would have assumed would really be equivalent.
So, what am I doing wrong?
Cheers
Ron Eastman
Lawrence Livermore National Laboratory
L-041
7000 East Avenue, PO Box 808, Livermore California 94551
001-925-423-7340
reastman@llnl.gov
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// ------------------- Main.C ----------------------
#include "TROOT.h"
#include "TRint.h"
extern void InitGui(); // initializer for GUI needed for interactive interface
VoidFuncPtr_t initfuncs[] = { InitGui, 0 };
double gX;
// Initialize the ROOT system
TROOT root("Rint","The ROOT Interactive Interface", initfuncs);
int main(int argc, char **argv)
{
gX = 3.0;
// Create interactive interface
TRint *theApp = new TRint("ROOT batch example", &argc, argv, NULL, 0);
// Run interactive interface
theApp->Run(kTRUE);
printf("main: the value of gX is now %f\n", gX);
return(0);
}
//--------------------------------------------------
// ----------------- TestClass.h -------------
#ifndef _TestClass_included_
#define _TestClass_included_
#include <math.h>
#include "Rtypes.h" // needed for ClassDef() macro
void gFunc(float p); // define a function
extern double gX; // an external variable
class TestClass1 { // and a class
public:
TestClass1(){}; // a constructor
void Dummy(); // will print something profound
int ijk; // an int
ClassDef(TestClass1,1)
};
#endif
//--------------------- TestClass.C ---------------------
#include <stdio.h>
//*KEEP,TestClass.
#include "TestClass.h"
//*KEND.
void gFunc(float p){
printf("gFunc: the value of p is %f\n", p);
return;
}
ClassImp(TestClass1)
void TestClass1::Dummy()
{
printf("hi there.\n");
return;
}
// ---------------------- Makefile ----------------------
#---------------------------------------------------
#SHELL=/bin/sh
CXXFLAGS = -g -Wall -fPIC -I$(ROOTSYS)/include
LDFLAGS = -g
LD = g++
DllSuf = so
SOFLAGS = -Wl,-soname, -shared
OPENGL=/usr/local
ROOTGLIBS = -lGpad -lGX11 -lMotif -lWidgets -lX3d
ROOTLIBS = -L$(ROOTSYS)/lib -lNew -lBase -lCint -lClib -lCont -lFunc \
-lGraf -lGraf3d -lHist -lHtml -lMatrix -lMeta -lMinuit -lNet \
-lPostscript -lProof -lRint -lTree -lUnix -lZip
GLIBS = $(OPENGL)/lib/*.so
LIBS = -L/usr/X11/lib $(ROOTLIBS) $(ROOTGLIBS) -ldl -lXm -lXt -lX11 -lm -rdynamic
# -lPW
HDRS = TestClass.h LinkDef.h
SRCS = Main.C TestClass.C
OBJS = Main.o TestClass.o MyDict.o
PROGRAM = myroot
all: $(PROGRAM)
$(PROGRAM): $(OBJS)
@echo "Linking $(PROGRAM) ..."
$(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
@echo "done"
clean:; @rm -f $(OBJS) core MyDict.* myroot
###
TestClass.o: TestClass.C TestClass.h
MyDict.o: MyDict.C
MyDict.C: LinkDef.h TestClass.h
@ echo "Generating dictionary ..."
test -f MyDict.C && /bin/rm MyDict.C ; \
test -f MyDict.h && /bin/rm MyDict.h ; \
rootcint -f MyDict.C -c TestClass.h LinkDef.h
#---------------------------------------------------
// ------------- LinkDef.h which works -----------------
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class TestClass1;
#pragma link C global gX;
#pragma link C++ function gFunc;
#endif