Making shared library for IO

Hi experts and ROOT friends,

ROOT asked me to provide a dictionary for the vector of vector when I tried to compile the following file util.cc which is used in the main function.

I followed the instructions on the official tutorial, generated the LinkDef.h, and compiled it using rootcling shown in the Makefile below, and it seems to link successfully to the executable.

However, it failed at run time and I have no idea how to debug from here. The error message is attached in the log.txt file. A testing main function is also attached.
log.txt (5.1 KB)
test.cc (242 Bytes)

Please let me know if you could provide any hints or directions.
Thank you very much!
Maxwell

ROOT Version: 6.26/04
Platform: Ubuntu 18.04.1 LTS
Compiler: g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0


// util.cc
void prepare(TFile *inputFile)
{
    
    std::vector<std::vector<float>> *GlobalPosition;

    TTree *tree;
    tree = static_cast<TTree *>(inputFile->Get("tree"));

    TBranch *b_GlobalPosition;
    tree->SetBranchAddress("GlobalPosition", &GlobalPosition, &b_GlobalPosition);


    b_GlobalPosition->GetEntry(0);
    std::cout<<"Event size is "<<b_GlobalPosition->GetEntries();

}
//LinkDef.h
#ifdef __CLING__

#pragma link C++ class std::vector < std::vector < float>> + ;

#endif
#makefile
LIB := $(shell root-config --libs)
CFLAGS := $(shell root-config --cflags)
INC := $(shell root-config --incdir)


run : build
	./test

build: makeLib test

test: src/test.cc libUtilLib.so
	g++ src/test.cc -o $@ -I$(INC) $(LIB) $(CFLAGS) -L$(PWD) -lUtilLib -Wl,-rpath,$(PWD)

makeLib: libUtilLib.so

libUtilLib.so: UtilDict.cxx src/util.cc
	g++ -shared -o $@ -I$(INC) -fPIC $^ 

UtilDict.cxx: ./include/LinkDef.h 	
	rootcling -f $@ $^

clean:
	rm *.so test *Dict*

At least: static std::vector<std::vector<float>> *GlobalPosition = 0;

1 Like

In case it helps: GitHub - eguiraud/root_dictionaries_tutorial: A tutorial on creating ROOT dictionaries to perform I/O of custom C++ classes

1 Like

Thank you! This indeed solves the problem. Could you explain a bit more why does it need to be a static type? It’s not clear to me.

This variable must live as long as the β€œtree”. I don’t see you delete the β€œtree” so the simplest fix was to use β€œstatic”.
BTW. The crucial fix was adding β€œ= 0”

Thank you again for the explanation.
In this case, why do we have to initialize the pointer to null (besides being a good habit)? Naively, I think tree->SetBranchAddress() would take care of it.

That pointer must be β€œinitialized” as you could also have β€œGlobalPosition = new vector<...>;” and then ROOT would use the already created object.
BTW. You should β€œdelete GlobalPosition;” once it is no longer needed (regardless if you created it or ROOT did). At the end of your routine, you could either β€œdelete tree;” or β€œtree->ResetBranchAdresses();” and then β€œdelete GlobalPosition;”. In your simple code, you can skip it as it will not create any big memory leaks, of course.

Very reasonable! Thank you very much!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.