gSystem->Load() not working in a macro

Hi,

I’ve created and compiled my own class and want to use it in a macro then run it via CINT. But when I use gSystem->Load() in the macro, it fails and complains class is declared but not defined. If prior to running the macro I issue the gSystem->Load() command from CINT, everything runs fine. I even check the status returned by Load() and it seems to make sense. It reports 0 when run from the macro, reports 1 when run after I load the shared library in CINT first. If I read the documentation right 0 means that it loaded it with no problems and 1 means it was already loaded. Why is Load() not working correctly then?

Here’s my simple macro:

#include "TROOT.h"
#include "TSystem.h"

#include <iostream>

#include "tClass.h"

void testT()
{
  Int_t status = gSystem->Load("./libtClass.so");
  std::cout << "status: " << status << std::endl;

  tClass *t = new tClass();
  
  t->setX(1.1);

  std::cout << "t->GetX(): " << t->getX() << std::endl;
}

Here’s my root session where I just run the macro without loading the shared lib explicitly before running:

root [0] .x testT.cxx
status: 0
Error: tClass() declared but not defined testT.cxx:14:
*** Interpreter error recovered ***

Here’s my root session if I first load the library before running:

root [0] gSystem->Load("./libtClass.so");
root [1] .x testT.cxx                    
t->GetX(): 1.1

Hi,

CINT takes the definition of tClass from tClass.h if the library hasn’t been loaded before.

You can simply create a rootmap file which will allow ROOT to automatically load libtClass.so when encountering tClass. The syntax is trivial, see e.g. $ROOTSYS/lib/libCore.rootmap.

Cheers, Axel.

[quote=“Axel”]
CINT takes the definition of tClass from tClass.h if the library hasn’t been loaded before.

You can simply create a rootmap file which will allow ROOT to automatically load libtClass.so when encountering tClass.[/quote]

Thanks for the quick reply. Has something changed recenty with ROOT though? I’ve been doing this same procedure for a very long time and have never needed a rootmap file before. I just recently installed version 5.26 and started using it.

Hi,

Which version of ROOT did you see a different behavior with? Can you upload a complete running example showing this different behavior (i.e. so far I have not found a ROOT version + example that show the behavior your describe).

Thanks,
Philippe.

So I’ve included my minimal class that I can’t get to work properly. I can not upload the Makefile because I get error “The extension is not allowed” (for no extension), so I include it below.

I do “make” to make the shared library, then run testT.cxx in an interactive ROOT session using “.x testT.cxx”.

In the past when I’ve made dumb mistakes in my macros, I try compiling them, since I seem to get more useful error messages to help me hunt down the problem. When I do that with this macro I get the following back:

root [0] .x testT.cxx  
status: 0
Error: tClass() declared but not defined testT.cxx:13:
*** Interpreter error recovered ***
root [1] .x testT.cxx++
Info in <TUnixSystem::ACLiC>: creating shared library /home/whanlon/physics/des/snVeto/./testT_cxx.so
dlopen error: /home/whanlon/physics/des/snVeto/./testT_cxx.so: undefined symbol: _ZN6tClassC1Ev
Load Error: Failed to load Dynamic link library /home/whanlon/physics/des/snVeto/./testT_cxx.so
/usr/bin/ld: /home/whanlon/physics/des/snVeto/./testT_cxx_ACLiC_dict.o: undefined reference to symbol 'G__resetplocal'
/usr/bin/ld: note: 'G__resetplocal' is defined in DSO /usr/local/lib/root/libCint.so.5.26 so try adding it to the linker command line
/usr/local/lib/root/libCint.so.5.26: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
*** Interpreter error recovered ***

/usr/local/lib/root/libCint.so.5.26 exists and I can read it (nm for example), so I don’t understand the error message.

Thanks for your help!

ROOT_CFLAGS=`root-config --cflags`
CINC=-I.
#CFLAGS=-g $(ROOT_CFLAGS) $(CINC)
CFLAGS=$(OPTDEBUG) $(ROOT_CFLAGS) -fPIC $(CINC)

.PHONY: all clean

.DELETE_ON_ERROR:

bankobj = tClass.o
bankdictobj = tClassDict.o
bankshobj = libtClass.so

all: $(bankshobj)

# special rules rule!
$(bankobj): %.o: %.cxx %.h
	$(CXX) -c $(CFLAGS) $<

$(bankdictobj): %Dict.o: %LinkDef.h %.o
	rootcint -f $(*)Dict.C -c $(CINC) $(*).h $(*)LinkDef.h
	$(CXX) -c $(*)Dict.C $(CFLAGS)

$(bankshobj): lib%.so: %.o %Dict.o
	$(CXX) $(OPTDEBUG) -shared $(*).o $(*)Dict.o -o $@

clean:
	rm -f $(bankobj) $(bankdictobj) $(bankshobj) tClassDict.C tClassDict.h

testT.cxx (305 Bytes)
tClassLinkDef.h (155 Bytes)
tClass.cxx (107 Bytes)
tClass.h (289 Bytes)

Hi,

With which version of ROOT where you using this successfully?

Philippe.

OK, I’ve figured out the problem. In the macro I had the line:

#include "tClass.h"

If I remove that line. It runs fine. Why does including the class header in the macro cause this weird error?

Hi,

That is because that lines (without a rootmap file) tells CINT that the class will be interpreted and then the loading of the library tries (and fails) to tell CINT that the class should use compile code.

Are you saying that the code with #include “tClass.h” actually never worked in any ROOT version? If it did work (i.e. used to work as you mentioned as the beginning of this post), which version of ROOT was it working with?

Philippe.

[quote=“pcanal”]
Are you saying that the code with #include “tClass.h” actually never worked in any ROOT version? If it did work (i.e. used to work as you mentioned as the beginning of this post), which version of ROOT was it working with?[/quote]

Sorry. When I said I’ve been doing this same procedure for a while, I meant the scheme of creating my own class, using the Makefile I provided, generating the dictionary, etc. I looked at some older macros where I’ve instantiated my own class and I indeed did not include the header.

Thank you for your help.

Will