RDF compiling C++ libraries and using functions in Define()

Dear experts,

I’m trying to define functions in C++ that I can compile to make my code run a little bit faster. I’m taking inspiration from the PyRoot manual to know what I should do and transpose it to RDF. The issue is that it is not working as I would like it to.

Basically, I have two files helper.h and helper.cpp. Their content is as follows
helper.h

#include "ROOT/RVec.hxx"
using namespace ROOT::VecOps;

class muon {
  public:
    RVec<float> dimuonKinematics(RVec<float>pt , RVec<float> eta, RVec<float> phi, RVec<float> m);
};

helper.cpp

#include "helper.h"

#include "ROOT/RVec.hxx"
#include "Math/LorentzVector.h"
#include "Math/Vector4D.h"
using namespace ROOT::VecOps;

template <typename T>
RVec<T> dimuonKinematics(const RVec<T>& pt, const RVec<T>& eta, const RVec<T>& phi){
  using PtEtaPhiMVectorD = ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<T>>;
  T muonRestMass = 0.1056583715;
  if (pt.size() != 2) return RVec<T> {};
  else{
    PtEtaPhiMVectorD P(0.,0.,0.,0.);
    
    PtEtaPhiMVectorD p1(pt[0], eta[0], phi[0], muonRestMass);
    PtEtaPhiMVectorD p2(pt[1], eta[1], phi[1], muonRestMass);

    P = p1 + p2;
    T Pt = P.Pt();
    T Pz = P.Pz();
    T M = P.M();
    T E = P.E();
    T Eta = P.Eta();
    T Y = log( (E + Pz) / pow( pow(M, 2) + pow(Pt, 2) , 1/2) );
    T Phi = P.Phi();
        
    RVec<T> dimuon {Pt, Eta, Phi, M, Y};
    
    return dimuon;
  };
};

I try from the CLI the following

>> import ROOT
>>> ROOT.gInterpreter.ProcessLine('#include "helper.h"')
0
>>> ROOT.gInterpreter.Load('libHelper.so')
0
>>> d = ROOT.RDataFrame("Events", "~/pnfs/ScoutingSkim/2022/DY/M-10to50/GenPartInfo/output_3844.1.root")
>>> d = d.Define("dimuonKinematics", 'muon().dimuonKinematics(ScoutingMuon_pt, ScoutingMuon_eta, ScoutingMuon_phi, ScoutingMuon_m)')
IncrementalExecutor::executeFunction: symbol '_ZN4muon16dimuonKinematicsEN4ROOT6VecOps4RVecIfEES3_S3_S3_' unresolved while linking [cling interface function]!
You are probably missing the definition of muon::dimuonKinematics(ROOT::VecOps::RVec<float>, ROOT::VecOps::RVec<float>, ROOT::VecOps::RVec<float>, ROOT::VecOps::RVec<float>)
Maybe you need to load the corresponding shared library?
terminate called after throwing an instance of 'std::runtime_error'
  what():  
An error occurred during just-in-time compilation in RLoopManager::Run. The lines above might indicate the cause of the crash
All RDF objects that have not run their event loop yet should be considered in an invalid state.

I know the function works because I’ve compiled it without issue using g++ -o libHelper.so -shared -fPIC `root-config --libs --cflags` helper.cxx -I ./ (getting this line from this post and when I’m just putting it in the header file it behaves as expected.

I think the solution should be something like suggested here.

Thanks for your help.


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.32.06
Platform: EL9
Compiler: ?