Hi,
I guess I’m mainly looking for the input of @Axel and/or @eguiraud on this one.
I’m trying to see if I could generalise an algorithm in our analysis software a bit. Instead of that piece of the code relying on the concrete type definitions of most of our EDM, I’d like to call on ROOT to do some operations for us.
First of all, I’d need ROOT to create (for instance) an object of type xAOD::ElectronContainer. But not with its default constructor. (Then I could just use TClass::New
…) So I was trying to make the following piece of code work:
// ROOT include(s):
#include <TInterpreter.h>
#include <TClass.h>
#include <TString.h>
#include <TError.h>
int main() {
// The name of this test:
static const char* APP_NAME = "jitTest";
// The type of the function we're after:
typedef void* ( *function_t )( void );
// Access the type we want to create, just to make sure that it is loaded:
TClass* cl = TClass::GetClass( "xAOD::ElectronContainer" );
if( ! cl ) {
Error( APP_NAME, "Couldn't load class" );
return 1;
}
Info( APP_NAME, "Loaded dictionary for class: %s", cl->GetName() );
// Declare a new function to the interpreter:
TInterpreter::EErrorCode ecode;
gInterpreter->Declare( Form( "void* createElectrons() { return new %s( SG::VIEW_ELEMENTS ); }",
cl->GetName() ) );
// Get a pointer to that function:
function_t func = ( function_t ) gInterpreter->Calc( "&createElectrons", &ecode );
if( ecode != TInterpreter::EErrorCode::kNoError ) {
Error( APP_NAME, "Failed to jit the function" );
return 1;
}
// Use the function:
void* electronsRaw = (*func)();
// Return gracefully:
return 0;
}
But it doesn’t. I get the following from it at runtime:
[bash][tauriel]:build > ./jitTest
Info in <jitTest>: Loaded dictionary for class: DataVector<xAOD::Electron_v1>
input_line_26:1:38: error: too few template arguments for class template 'DataVector'
void* createElectrons() { return new DataVector<xAOD::Electron_v1>( SG::VIEW_ELEMENTS ); }
^
input_line_24:1:44: note: template is declared here
template <typename T, typename BASE> class DataVector;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
input_line_28:2:5: error: use of undeclared identifier 'createElectrons'
(& createElectrons)
^
libc++abi.dylib: terminating with uncaught exception of type cling::CompilationException: Error evaluating expression (& createElectrons)
Abort trap: 6
[bash][tauriel]:build >
Note that if I don’t use the xAOD::ElectronContainer type in my JIT compiled function, then this setup does work. (I’m able to get a pointer to the compiled function, and use it.)
At this point I’m leaning towards blaming ROOT… Since you see, the xAOD::ElectronContainer
type is absolutely known to ROOT. If I open an interactive session from the same environment where I’m trying to run this test executable, I can absolutely do this:
[bash][tauriel]:build > root -b
------------------------------------------------------------
| Welcome to ROOT 6.12/06 http://root.cern.ch |
| (c) 1995-2017, The ROOT Team |
| Built for macosx64 |
| From tag v6-12-06, 9 February 2018 |
| Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' |
------------------------------------------------------------
root [0] xAOD::ElectronContainer c( SG::VIEW_ELEMENTS );
root [1] .q
[bash][tauriel]:build >
So… What am I missing? Why doesn’t TInterpreter
want to understand my code correctly?
Note that I can force TInterpreter
into working, if I jump through some hoops. Like:
gInterpreter->Declare( Form( "#define XAOD_STANDALONE\n#define ROOTCORE\n#define XAOD_ANALYSIS\n#include <xAODEgamma/ElectronContainer.h>\nvoid* createElectrons() { return new %s( SG::VIEW_ELEMENTS ); }",
cl->GetName() ) );
But there are multiple problems here:
- I don’t want to have to know in the code what header to include in order to be able to use some random type;
- Using our headers is a bit tricky, as they rely on some definitions to work correctly. The dictionaries do know about these definitions, but if I try to include one of these headers like this, I have to set them all by hand…
So… Any suggestions?
Cheers,
Attila
ROOT Version: 6.12/06
Platform: x86_64-mac1013-clang92-opt
Compiler: Xcode/clang 9.1