Hi all,
I use this environment:
- cmake version 3.22.2
- gcc version 9.3.0 (GCC)
- ROOT Version: 6.22/08 (for linuxx8664gcc from tags/v6-22-08@v6-22-08)
- Python 3.9.2
Basically, I first build (build.sh
) a library with a function (make_vector
) and a dictionary for a stl collection of TVector3 with the following CMakeLists.txt
:
cmake_minimum_required(VERSION 3.0)
project(TVector3VecDictPrj CXX)
find_package(ROOT)
include(${ROOT_USE_FILE})
add_library(MyLib SHARED src/myCode.cpp)
target_include_directories(MyLib PUBLIC include)
target_link_libraries(MyLib ${ROOT_LIBRARIES})
ROOT_GENERATE_DICTIONARY(TVector3VecDict MODULE MyLib TVector3.h LINKDEF LinkDef.h)
install(TARGETS MyLib LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/lib)
install(
DIRECTORY "${CMAKE_BINARY_DIR}/."
DESTINATION "${PROJECT_SOURCE_DIR}/lib"
FILES_MATCHING PATTERN "*.pcm"
PATTERN ".cmake" EXCLUDE
PATTERN "CMakeFiles" EXCLUDE)
The source is:
#include "myCode.h"
ROOT::VecOps::RVec<TVector3> make_vector(ROOT::VecOps::RVec<double> x, ROOT::VecOps::RVec<double> y, ROOT::VecOps::RVec<double> z) {
ROOT::VecOps::RVec<TVector3> vs;
for(unsigned int i = 0; i < x.size(); i++)
{
vs.push_back({x[i], y[i], z[i]});
}
return vs;
}
The header is:
#ifndef __MYCODE_H__
#define __MYCODE_H__
#include <TVector3.h>
#include <ROOT/RVec.hxx>
ROOT::VecOps::RVec<TVector3> make_vector(ROOT::VecOps::RVec<double> x, ROOT::VecOps::RVec<double> y, ROOT::VecOps::RVec<double> z);
#endif
Then, in the script (process.py
) a TTree is created and passed to a RDataFrame. A new column of the RDataFrame is created with the function make_vector
and finally the RDataFrame is written into an output file. Here the script:
#!/usr/bin/env python3
import ROOT as r
r.gSystem.Load("lib/libMyLib.so")
r.gInterpreter.AddIncludePath("include")
r.gInterpreter.ProcessLine('#include "myCode.h"')
vx = r.std.vector["double"]()
vy = r.std.vector["double"]()
vz = r.std.vector["double"]()
for i in range(3):
vx.push_back(float(i))
vy.push_back(float(i))
vz.push_back(float(i))
t = r.TTree("myTree","myTree")
t.Branch("x", vx)
t.Branch("y", vy)
t.Branch("z", vz)
for i in range(3):
t.Fill()
df = r.RDataFrame(t)
df = df.Define("v","make_vector(x,y,z)")
df.Snapshot("myTree","myFile.root")
What I get, when I run the script, is:
Error in <TTree::Branch>: The class requested (vector<TVector3,ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >) for the branch "v" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector<TVector3,ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >) to avoid to write corrupted data.
But naively checking the library, I get:
bash-4.2$ nm -C lib/libMyLib.so | grep "vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >"
000000000000bdec W __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >::__normal_iterator(TVector3* const&)
000000000000bdec W __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >::__normal_iterator(TVector3* const&)
000000000000befd W __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >::difference_type __gnu_cxx::operator-<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >(__gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > > const&, __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > > const&)
000000000000bf82 W __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >::base() const
000000000000c030 W __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >::operator*() const
000000000000bfe4 W __gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >::operator-(long) const
000000000000be0a W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::_M_check_len(unsigned long, char const*) const
000000000000c104 W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::size() const
000000000000c0e2 W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::max_size() const
000000000000c28f W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::_S_max_size(ROOT::Detail::VecOps::RAdoptAllocator<TVector3> const&)
000000000000b920 W TVector3& std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::emplace_back<TVector3>(TVector3&&)
000000000000ba8c W void std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::_M_realloc_insert<TVector3>(__gnu_cxx::__normal_iterator<TVector3*, std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> > >, TVector3&&)
000000000000ba62 W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::end()
000000000000bcfc W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::back()
000000000000bed4 W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::begin()
000000000000b81c W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::push_back(TVector3&&)
000000000000b62e W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::vector()
000000000000b62e W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::vector()
000000000000b666 W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::~vector()
000000000000b666 W std::vector<TVector3, ROOT::Detail::VecOps::RAdoptAllocator<TVector3> >::~vector()
suggesting that the dictionary is there, so the question is what is wrong with this code or compilation?
code.tar.gz (1.4 KB)