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;

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

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!